~ubuntu-branches/ubuntu/precise/lilypond/precise

« back to all changes in this revision

Viewing changes to lily/stencil-scheme.cc

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Bushnell, BSG
  • Date: 2006-12-19 10:18:12 UTC
  • mfrom: (3.1.4 feisty)
  • Revision ID: james.westby@ubuntu.com-20061219101812-7awtjkp0i393wxty
Tags: 2.8.7-3
scripts/midi2ly.py: When setting DATADIR, find Lilypond python files
in the @TOPLEVEL_VERSION@ directory, not 'current'.  Patch thanks to
Chris Lamb (chris@chris-lamb.co.uk).  (Closes: #400550)

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
 
4
4
  source file of the GNU LilyPond music typesetter
5
5
 
6
 
  (c) 1997--2004 Han-Wen Nienhuys <hanwen@cs.uu.nl>
 
6
  (c) 1997--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
7
7
*/
8
8
 
 
9
 
9
10
#include "font-metric.hh"
 
11
#include "libc-extension.hh"
 
12
#include "lookup.hh"
10
13
#include "stencil.hh"
11
14
 
12
15
/*
13
16
  TODO: naming add/combine.
14
 
 */
15
 
/*
16
 
  UMGH. junkme!
17
 
  
18
 
 */
19
 
LY_DEFINE (ly_stencil_set_extent_x, "ly:stencil-set-extent!",
20
 
           3, 0, 0, (SCM stil, SCM axis, SCM np),
21
 
           "Set the extent of @var{stil} "
22
 
           "(@var{extent} must be a pair of numbers) "
23
 
           "in @var{axis} direction (0 or 1 for x- and y-axis respectively).")
24
 
{
25
 
  Stencil *s = unsmob_stencil (stil);
26
 
  SCM_ASSERT_TYPE (s, stil, SCM_ARG1, __FUNCTION__, "stencil");
27
 
  SCM_ASSERT_TYPE (is_axis (axis), axis, SCM_ARG2, __FUNCTION__, "axis");
28
 
  SCM_ASSERT_TYPE (is_number_pair (np), np, SCM_ARG3, __FUNCTION__,
29
 
                   "number pair");
30
 
 
31
 
  Interval iv = ly_scm2interval (np);
32
 
  s->dim_[Axis (gh_scm2int (axis))] = iv;
33
 
 
34
 
  return SCM_UNDEFINED;
35
 
}
 
17
*/
36
18
 
37
19
LY_DEFINE (ly_translate_stencil_axis, "ly:stencil-translate-axis",
38
20
           3, 0, 0, (SCM stil, SCM amount, SCM axis),
40
22
{
41
23
  Stencil *s = unsmob_stencil (stil);
42
24
  SCM_ASSERT_TYPE (s, stil, SCM_ARG1, __FUNCTION__, "stencil");
43
 
  SCM_ASSERT_TYPE (gh_number_p (amount), amount, SCM_ARG2, __FUNCTION__, "number pair");
 
25
  SCM_ASSERT_TYPE (scm_is_number (amount), amount, SCM_ARG2, __FUNCTION__, "number");
 
26
 
 
27
  Real real_amount = scm_to_double (amount);
 
28
 
 
29
#if 0
 
30
  SCM_ASSERT_TYPE (!isinf (real_amount) && !isnan (real_amount),
 
31
                   amount, SCM_ARG2, __FUNCTION__, "finite number");
 
32
#endif
 
33
 
44
34
  SCM_ASSERT_TYPE (is_axis (axis), axis, SCM_ARG3, __FUNCTION__, "axis");
45
35
 
46
36
  SCM new_s = s->smobbed_copy ();
47
37
  Stencil *q = unsmob_stencil (new_s);
48
 
  q->translate_axis (gh_scm2double (amount), Axis (gh_scm2int (axis)));
 
38
  q->translate_axis (real_amount, Axis (scm_to_int (axis)));
49
39
  return new_s;
50
 
 
51
40
}
52
41
 
53
42
LY_DEFINE (ly_translate_stencil, "ly:stencil-translate",
61
50
  Offset o = ly_scm2offset (offset);
62
51
 
63
52
  SCM new_s = s->smobbed_copy ();
64
 
  Stencil *q =unsmob_stencil (new_s);
 
53
  Stencil *q = unsmob_stencil (new_s);
65
54
  q->translate (o);
66
55
  return new_s;
67
56
}
68
57
 
69
 
LY_DEFINE (ly_stencil_get_expr, "ly:stencil-get-expr",
 
58
LY_DEFINE (ly_stencil_expr, "ly:stencil-expr",
70
59
           1, 0, 0, (SCM stil),
71
60
           "Return the expression of @var{stil}.")
72
61
{
73
62
  Stencil *s = unsmob_stencil (stil);
74
63
  SCM_ASSERT_TYPE (s, stil, SCM_ARG1, __FUNCTION__, "stencil");
75
 
  return s->get_expr ();
 
64
  return s->expr ();
76
65
}
77
66
 
78
 
LY_DEFINE (ly_stencil_get_extent, "ly:stencil-extent",
 
67
LY_DEFINE (ly_stencil_extent, "ly:stencil-extent",
79
68
           2, 0, 0, (SCM stil, SCM axis),
80
69
           "Return a pair of numbers signifying the extent of @var{stil} in "
81
70
           "@var{axis} direction (0 or 1 for x and y axis respectively).")
84
73
  SCM_ASSERT_TYPE (s, stil, SCM_ARG1, __FUNCTION__, "stencil");
85
74
  SCM_ASSERT_TYPE (is_axis (axis), axis, SCM_ARG2, __FUNCTION__, "axis");
86
75
 
87
 
  return ly_interval2scm (s->extent (Axis (gh_scm2int (axis))));
 
76
  return ly_interval2scm (s->extent (Axis (scm_to_int (axis))));
 
77
}
 
78
 
 
79
LY_DEFINE (ly_stencil_empty_p, "ly:stencil-empty?",
 
80
           1, 0, 0, (SCM stil),
 
81
           "Return whether @var{stil} is empty ")
 
82
{
 
83
  Stencil *s = unsmob_stencil (stil);
 
84
  SCM_ASSERT_TYPE (s, stil, SCM_ARG1, __FUNCTION__, "stencil");
 
85
  return scm_from_bool (s->is_empty ());
 
86
}
 
87
 
 
88
LY_DEFINE (ly_stencil_origin, "ly:stencil-origin",
 
89
           2, 0, 0, (SCM stil, SCM axis),
 
90
           "Return a pair of numbers signifying the origin @var{stil} in "
 
91
           "@var{axis} direction (0 or 1 for x and y axis respectively).")
 
92
{
 
93
  Stencil *s = unsmob_stencil (stil);
 
94
  SCM_ASSERT_TYPE (s, stil, SCM_ARG1, __FUNCTION__, "stencil");
 
95
  SCM_ASSERT_TYPE (is_axis (axis), axis, SCM_ARG2, __FUNCTION__, "axis");
 
96
 
 
97
  return scm_from_double (s->origin ()[Axis (scm_to_int (axis))]);
88
98
}
89
99
 
90
100
LY_DEFINE (ly_stencil_moved_to_edge, "ly:stencil-moved-to-edge",
95
105
{
96
106
  /*
97
107
    C&P from combine-at-edge.
98
 
   */
 
108
  */
99
109
  Stencil *s1 = unsmob_stencil (first);
100
110
  Stencil *s2 = unsmob_stencil (second);
101
111
  Stencil first_stencil;
106
116
  Real p = 0.0;
107
117
  if (padding != SCM_UNDEFINED)
108
118
    {
109
 
      SCM_ASSERT_TYPE (gh_number_p (padding), padding, SCM_ARG5, __FUNCTION__, "number");
110
 
      p = gh_scm2double (padding);
 
119
      SCM_ASSERT_TYPE (scm_is_number (padding), padding, SCM_ARG5, __FUNCTION__, "number");
 
120
      p = scm_to_double (padding);
111
121
    }
112
122
  Real m = 0.0;
113
123
  if (minimum != SCM_UNDEFINED)
114
124
    {
115
 
      SCM_ASSERT_TYPE (gh_number_p (minimum), minimum, SCM_ARG6, __FUNCTION__, "number");
116
 
      m = gh_scm2double (minimum);
 
125
      SCM_ASSERT_TYPE (scm_is_number (minimum), minimum, SCM_ARG6, __FUNCTION__, "number");
 
126
      m = scm_to_double (minimum);
117
127
    }
118
128
 
119
129
  if (s1)
120
130
    first_stencil = *s1;
121
131
 
122
132
  if (s2)
123
 
    return first_stencil.moved_to_edge (Axis (gh_scm2int (axis)),
124
 
                                        Direction (gh_scm2int (direction)),
 
133
    return first_stencil.moved_to_edge (Axis (scm_to_int (axis)),
 
134
                                        Direction (scm_to_int (direction)),
125
135
                                        *s2, p, m).smobbed_copy ();
126
136
  else
127
 
    return Stencil().smobbed_copy ();
 
137
    return Stencil ().smobbed_copy ();
128
138
}
129
139
 
130
 
 
131
 
  
132
140
LY_DEFINE (ly_stencil_combine_at_edge, "ly:stencil-combine-at-edge",
133
 
           4, 2, 0,  (SCM first, SCM axis, SCM direction,
134
 
                      SCM second,
135
 
                      SCM padding,
136
 
                      SCM minimum),
 
141
           4, 2, 0, (SCM first, SCM axis, SCM direction,
 
142
                     SCM second,
 
143
                     SCM padding,
 
144
                     SCM minimum),
137
145
           "Construct a stencil by putting @var{second} next to @var{first}. "
138
146
           "@var{axis} can be 0 (x-axis) or 1 (y-axis), "
139
147
           "@var{direction} can be -1 (left or down) or 1 (right or up). "
140
148
           "The stencils are juxtaposed with  @var{padding} as extra space. "
141
149
           "If this puts the reference points closer than @var{minimum}, "
142
 
           "they are moved by the latter amount.")
 
150
           "they are moved by the latter amount."
 
151
           "@var{first} and @var{second} may also be '() or #f.")
143
152
{
144
153
  Stencil *s1 = unsmob_stencil (first);
145
154
  Stencil *s2 = unsmob_stencil (second);
146
155
  Stencil result;
147
156
 
148
 
  SCM_ASSERT_TYPE (is_axis (axis), axis, SCM_ARG3, __FUNCTION__, "axis");
149
 
  SCM_ASSERT_TYPE (is_direction (direction), direction, SCM_ARG4, __FUNCTION__, "dir");
 
157
  SCM_ASSERT_TYPE (s1 || first == SCM_BOOL_F || first == SCM_EOL,
 
158
                   first, SCM_ARG1, __FUNCTION__, "Stencil, #f or ()");
 
159
  SCM_ASSERT_TYPE (s2 || second == SCM_BOOL_F || second == SCM_EOL,
 
160
                   second, SCM_ARG4, __FUNCTION__, "Stencil, #f or ()");
 
161
  SCM_ASSERT_TYPE (is_axis (axis), axis, SCM_ARG2, __FUNCTION__, "axis");
 
162
  SCM_ASSERT_TYPE (is_direction (direction), direction, SCM_ARG3, __FUNCTION__, "dir");
150
163
 
151
164
  Real p = 0.0;
152
165
  if (padding != SCM_UNDEFINED)
153
166
    {
154
 
      SCM_ASSERT_TYPE (gh_number_p (padding), padding, SCM_ARG5, __FUNCTION__, "number");
155
 
      p = gh_scm2double (padding);
 
167
      SCM_ASSERT_TYPE (scm_is_number (padding), padding, SCM_ARG5, __FUNCTION__, "number");
 
168
      p = scm_to_double (padding);
156
169
    }
157
170
  Real m = 0.0;
158
171
  if (minimum != SCM_UNDEFINED)
159
172
    {
160
 
      SCM_ASSERT_TYPE (gh_number_p (minimum), minimum, SCM_ARG6, __FUNCTION__, "number");
161
 
      m = gh_scm2double (minimum);
 
173
      SCM_ASSERT_TYPE (scm_is_number (minimum), minimum, SCM_ARG6, __FUNCTION__, "number");
 
174
      m = scm_to_double (minimum);
162
175
    }
163
176
 
164
177
  if (s1)
165
178
    result = *s1;
 
179
 
166
180
  if (s2)
167
 
    result.add_at_edge (Axis (gh_scm2int (axis)),
168
 
                        Direction (gh_scm2int (direction)), *s2, p, m);
 
181
    result.add_at_edge (Axis (scm_to_int (axis)),
 
182
                        Direction (scm_to_int (direction)), *s2, p, m);
169
183
 
170
184
  return result.smobbed_copy ();
171
185
}
172
186
 
173
 
LY_DEFINE (ly_stencil_add , "ly:stencil-add",
 
187
LY_DEFINE (ly_stencil_add, "ly:stencil-add",
174
188
           0, 0, 1, (SCM args),
175
189
           "Combine stencils. Takes any number of arguments.")
176
190
{
177
191
#define FUNC_NAME __FUNCTION__
178
192
  SCM_VALIDATE_REST_ARGUMENT (args);
179
193
 
180
 
  Stencil result;
 
194
  SCM expr = SCM_EOL;
 
195
  SCM *tail = &expr;
 
196
  Box extent;
 
197
  extent.set_empty ();
181
198
 
182
199
  while (!SCM_NULLP (args))
183
200
    {
184
 
      Stencil *s = unsmob_stencil (gh_car (args));
 
201
      Stencil *s = unsmob_stencil (scm_car (args));
185
202
      if (!s)
186
 
        SCM_ASSERT_TYPE (s, gh_car (args), SCM_ARGn, __FUNCTION__, "Stencil");
 
203
        SCM_ASSERT_TYPE (s, scm_car (args), SCM_ARGn, __FUNCTION__, "Stencil");
187
204
 
188
 
      result.add_stencil (*s);
189
 
      args = gh_cdr (args);
 
205
      extent.unite (s->extent_box ());
 
206
      *tail = scm_cons (s->expr (), SCM_EOL);
 
207
      tail = SCM_CDRLOC (*tail);
 
208
      args = scm_cdr (args);
190
209
    }
191
210
 
192
 
  return result.smobbed_copy ();
 
211
  expr = scm_cons (ly_symbol2scm ("combine-stencil"), expr);
 
212
  return Stencil (extent, expr).smobbed_copy ();
193
213
}
194
214
 
195
215
LY_DEFINE (ly_make_stencil, "ly:make-stencil",
196
 
           3, 0, 0,  (SCM expr, SCM xext, SCM yext),
 
216
           3, 0, 0, (SCM expr, SCM xext, SCM yext),
197
217
           " \n"
198
218
           "Stencils are a device independent output expressions."
199
219
           "They carry two pieces of information: \n\n"
200
220
           "1: a specification of how to print this object. "
201
221
           "This specification is processed by the output backends, "
202
 
           " for example @file{scm/output-tex.scm}.\n\n"
 
222
           " for example @file{scm/output-ps.scm}.\n\n"
203
223
           "2: the vertical and horizontal extents of the object.\n\n")
204
224
{
 
225
  SCM_ASSERT_TYPE (!scm_is_pair (expr)
 
226
                   || is_stencil_head (scm_car (expr)),
 
227
                   expr, SCM_ARG1, __FUNCTION__, "registered stencil expression");
 
228
 
205
229
  SCM_ASSERT_TYPE (is_number_pair (xext), xext, SCM_ARG2, __FUNCTION__, "number pair");
206
230
  SCM_ASSERT_TYPE (is_number_pair (yext), yext, SCM_ARG3, __FUNCTION__, "number pair");
207
231
 
210
234
  return s.smobbed_copy ();
211
235
}
212
236
 
213
 
SCM
214
 
fontify_atom (Font_metric const *met, SCM f)
215
 
{
216
 
  if (f == SCM_EOL)
217
 
    return f;
218
 
  else
219
 
    return  scm_list_n (ly_symbol2scm ("fontify"),
220
 
                        ly_quote_scm (met->description_), f, SCM_UNDEFINED);
221
 
}
222
 
 
223
 
LY_DEFINE (ly_fontify_atom,"ly:fontify-atom",
224
 
           2, 0, 0, (SCM met, SCM f),
225
 
           "Add a font selection command for the font metric @var{met} "
226
 
           "to @var{f}.")
227
 
{
228
 
  SCM_ASSERT_TYPE (unsmob_metrics (met), met, SCM_ARG1, __FUNCTION__, "font metric");
229
 
 
230
 
  return fontify_atom (unsmob_metrics (met), f);
231
 
}
232
 
 
233
 
LY_DEFINE (ly_align_to_x, "ly:stencil-align-to!",
 
237
LY_DEFINE (ly_stencil_aligned_to, "ly:stencil-aligned-to",
234
238
           3, 0, 0, (SCM stil, SCM axis, SCM dir),
235
239
           "Align @var{stil} using its own extents. "
236
240
           "@var{dir} is a number -1, 1 are left and right respectively. "
237
 
           "Other values are interpolated (so 0 means the center. ")
 
241
           "Other values are interpolated (so 0 means the center).")
238
242
{
239
243
  SCM_ASSERT_TYPE (unsmob_stencil (stil), stil, SCM_ARG1, __FUNCTION__, "stencil");
240
244
  SCM_ASSERT_TYPE (is_axis (axis), axis, SCM_ARG2, __FUNCTION__, "axis");
241
 
  SCM_ASSERT_TYPE (gh_number_p (dir), dir, SCM_ARG3, __FUNCTION__, "number");
242
 
 
243
 
  unsmob_stencil (stil)->align_to ((Axis)gh_scm2int (axis),
244
 
                                   gh_scm2double (dir));
245
 
  return SCM_UNDEFINED;
 
245
  SCM_ASSERT_TYPE (scm_is_number (dir), dir, SCM_ARG3, __FUNCTION__, "number");
 
246
 
 
247
  Stencil target = *unsmob_stencil (stil);
 
248
 
 
249
  target.align_to ((Axis)scm_to_int (axis),
 
250
                   scm_to_double (dir));
 
251
  return target.smobbed_copy ();
 
252
}
 
253
 
 
254
LY_DEFINE (ly_stencil_fonts, "ly:stencil-fonts",
 
255
           1, 0, 0, (SCM s),
 
256
           " Analyse @var{s}, and return a list of fonts used in @var{s}.")
 
257
{
 
258
  Stencil *stil = unsmob_stencil (s);
 
259
  SCM_ASSERT_TYPE (stil, s, SCM_ARG1, __FUNCTION__, "Stencil");
 
260
  return find_expression_fonts (stil->expr ());
 
261
}
 
262
 
 
263
LY_DEFINE (ly_stencil_in_color, "ly:stencil-in-color",
 
264
           4, 0, 0, (SCM stc, SCM r, SCM g, SCM b),
 
265
           "Put @var{stc} in a different color.")
 
266
{
 
267
  Stencil *stil = unsmob_stencil (stc);
 
268
  SCM_ASSERT_TYPE (stil, stc, SCM_ARG1, __FUNCTION__, "Stencil");
 
269
  return Stencil (stil->extent_box (),
 
270
                  scm_list_3 (ly_symbol2scm ("color"),
 
271
                              scm_list_3 (r, g, b),
 
272
                              stil->expr ())).smobbed_copy ();
 
273
}
 
274
 
 
275
struct Stencil_interpret_arguments
 
276
{
 
277
  SCM func;
 
278
  SCM arg1;
 
279
};
 
280
 
 
281
void stencil_interpret_in_scm (void *p, SCM expr)
 
282
{
 
283
  Stencil_interpret_arguments *ap = (Stencil_interpret_arguments *) p;
 
284
  scm_call_2 (ap->func, ap->arg1, expr);
 
285
}
 
286
 
 
287
LY_DEFINE (ly_interpret_stencil_expression, "ly:interpret-stencil-expression",
 
288
           4, 0, 0, (SCM expr, SCM func, SCM arg1, SCM offset),
 
289
           "Parse EXPR, feed bits to FUNC with first arg ARG1")
 
290
{
 
291
  SCM_ASSERT_TYPE (ly_is_procedure (func), func, SCM_ARG1, __FUNCTION__,
 
292
                   "procedure");
 
293
 
 
294
  Stencil_interpret_arguments a;
 
295
  a.func = func;
 
296
  a.arg1 = arg1;
 
297
  Offset o = ly_scm2offset (offset);
 
298
 
 
299
  interpret_stencil_expression (expr, stencil_interpret_in_scm, (void *) & a, o);
 
300
 
 
301
  return SCM_UNSPECIFIED;
 
302
}
 
303
 
 
304
LY_DEFINE (ly_bracket, "ly:bracket",
 
305
           4, 0, 0,
 
306
           (SCM a, SCM iv, SCM t, SCM p),
 
307
           "Make a bracket in direction @var{a}. The extent of the bracket is "
 
308
           "given by @var{iv}. The wings protude by an amount of @var{p}, which "
 
309
           "may be negative. The thickness is given by @var{t}.")
 
310
{
 
311
  SCM_ASSERT_TYPE (is_axis (a), a, SCM_ARG1, __FUNCTION__, "axis");
 
312
  SCM_ASSERT_TYPE (is_number_pair (iv), iv, SCM_ARG2, __FUNCTION__, "number pair");
 
313
  SCM_ASSERT_TYPE (scm_is_number (t), a, SCM_ARG3, __FUNCTION__, "number");
 
314
  SCM_ASSERT_TYPE (scm_is_number (p), a, SCM_ARG4, __FUNCTION__, "number");
 
315
 
 
316
  return Lookup::bracket ((Axis)scm_to_int (a), ly_scm2interval (iv),
 
317
                          scm_to_double (t),
 
318
                          scm_to_double (p),
 
319
                          0.95 * scm_to_double (t)).smobbed_copy ();
 
320
}
 
321
 
 
322
LY_DEFINE (ly_filled_box, "ly:round-filled-box",
 
323
           3, 0, 0,
 
324
           (SCM xext, SCM yext, SCM blot),
 
325
           "Make a @code{Stencil} "
 
326
           "that prints a black box of dimensions @var{xext}, "
 
327
           "@var{yext} and roundness @var{blot}.")
 
328
{
 
329
  SCM_ASSERT_TYPE (is_number_pair (xext), xext, SCM_ARG1, __FUNCTION__, "number pair");
 
330
  SCM_ASSERT_TYPE (is_number_pair (yext), yext, SCM_ARG2, __FUNCTION__, "number pair");
 
331
  SCM_ASSERT_TYPE (scm_is_number (blot), blot, SCM_ARG3, __FUNCTION__, "number");
 
332
 
 
333
  return Lookup::round_filled_box (Box (ly_scm2interval (xext), ly_scm2interval (yext)),
 
334
                                   scm_to_double (blot)).smobbed_copy ();
 
335
}
 
336
 
 
337
LY_DEFINE (ly_register_stencil_expression, "ly:register-stencil-expression",
 
338
           1, 0, 0,
 
339
           (SCM symbol),
 
340
           "Add @var{symbol} as head of a stencil expression")
 
341
{
 
342
  SCM_ASSERT_TYPE (scm_is_symbol (symbol), symbol,
 
343
                   SCM_ARG1, __FUNCTION__, "Symbol");
 
344
  register_stencil_head (symbol);
 
345
  return SCM_UNSPECIFIED;
 
346
}
 
347
 
 
348
LY_DEFINE (ly_all_stencil_expressions, "ly:all-stencil-expressions",
 
349
           0, 0, 0,
 
350
           (),
 
351
           "Return all symbols recognized as stencil expressions.")
 
352
{
 
353
  return all_stencil_heads ();
246
354
}