[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[patch] \label, page references
From: |
Nicolas Sceaux |
Subject: |
[patch] \label, page references |
Date: |
Sat, 26 May 2007 18:34:24 +0200 |
User-agent: |
Gnus/5.11 (Gnus v5.11) Emacs/22.0.50 (darwin) |
Hi,
Here is a patch implementing a page reference markup feature.
A label is attached to a score or a top-level markup using a \label
command with a symbol argument. When the page breaking is done, a {
label -> page-number } table is filled, which can be referenced later to
retreive page numbers from a label. The patch introduces a new stencil
command, delay-stencil-evaluation, and a new markup command using it:
\page-ref.
nicolas
diff --git a/lily/include/page-marker.hh b/lily/include/page-marker.hh
index a925a6c..69962e6 100644
--- a/lily/include/page-marker.hh
+++ b/lily/include/page-marker.hh
@@ -17,12 +17,17 @@ class Page_marker
SCM symbol_; /* either 'page-turn-permission or 'page-break-permission */
SCM permission_; /* 'force, 'allow, or '() */
+ SCM label_; /* bookmarking label (a symbol) */
public:
- Page_marker (SCM symbol, SCM permission);
+ Page_marker ();
+ void set_permission (SCM symbol, SCM permission);
+ void set_label (SCM label);
+
SCM permission_symbol ();
SCM permission_value ();
+ SCM label ();
};
DECLARE_UNSMOB (Page_marker, page_marker)
diff --git a/lily/page-breaking.cc b/lily/page-breaking.cc
index 46a1eed..25cd4bb 100644
--- a/lily/page-breaking.cc
+++ b/lily/page-breaking.cc
@@ -235,6 +235,7 @@ Page_breaking::make_pages (vector<vsize>
SCM book = book_->self_scm ();
int first_page_number = robust_scm2int (book_->paper_->c_variable
("first-page-number"), 1);
SCM ret = SCM_EOL;
+ SCM label_page_table = SCM_EOL;
for (vsize i = 0; i < lines_per_page.size (); i++)
{
@@ -246,10 +247,29 @@ Page_breaking::make_pages (vector<vsize>
SCM page = scm_apply_0 (make_page,
scm_list_n (book, lines, page_num, rag, last,
SCM_UNDEFINED));
+ /* collect labels */
+ for (SCM l = lines ; scm_is_pair (l) ; l = scm_cdr (l))
+ {
+ SCM labels = SCM_EOL;
+ if (Grob * line = unsmob_grob (scm_car (l)))
+ {
+ System *system = dynamic_cast<System*> (line);
+ labels = system->get_property ("labels");
+ }
+ else if (Prob * markup = unsmob_prob (scm_car (l)))
+ labels = markup->get_property ("labels");
+
+ for (SCM lbls = labels ; scm_is_pair (lbls) ; lbls = scm_cdr (lbls))
+ label_page_table = scm_cons (scm_cons (scm_car (lbls), page_num),
+ label_page_table);
+ }
+
scm_apply_1 (page_stencil, page, SCM_EOL);
ret = scm_cons (page, ret);
systems = scm_list_tail (systems, line_count);
}
+ book_->paper_->set_variable (ly_symbol2scm ("label-page-table"),
+ scm_reverse_x (label_page_table, SCM_EOL));
ret = scm_reverse (ret);
return ret;
}
diff --git a/lily/page-marker-scheme.cc b/lily/page-marker-scheme.cc
index 3278a7b..f2450be 100644
--- a/lily/page-marker-scheme.cc
+++ b/lily/page-marker-scheme.cc
@@ -8,12 +8,24 @@
#include "page-marker.hh"
-LY_DEFINE (ly_make_page_marker, "ly:make-page-marker",
+LY_DEFINE (ly_make_page_permission_marker, "ly:make-page-permission-marker",
2, 0, 0,
(SCM symbol, SCM permission),
"Return page marker with page breaking and turning permissions.")
{
LY_ASSERT_TYPE (ly_is_symbol, symbol, 1);
- Page_marker *page_marker = new Page_marker (symbol, permission);
+ Page_marker *page_marker = new Page_marker ();
+ page_marker->set_permission (symbol, permission);
+ return page_marker->unprotect ();
+}
+
+LY_DEFINE (ly_make_page_label_marker, "ly:make-page-label-marker",
+ 1, 0, 0,
+ (SCM label),
+ "Return page marker with label.")
+{
+ LY_ASSERT_TYPE (ly_is_symbol, label, 1);
+ Page_marker *page_marker = new Page_marker ();
+ page_marker->set_label (label);
return page_marker->unprotect ();
}
diff --git a/lily/page-marker.cc b/lily/page-marker.cc
index dd43c35..11b1999 100644
--- a/lily/page-marker.cc
+++ b/lily/page-marker.cc
@@ -9,10 +9,11 @@
#include "page-marker.hh"
#include "ly-smobs.icc"
-Page_marker::Page_marker (SCM symbol, SCM permission)
+Page_marker::Page_marker ()
{
- symbol_ = symbol;
- permission_ = permission;
+ symbol_ = SCM_EOL;
+ permission_ = SCM_EOL;
+ label_ = SCM_EOL;
smobify_self ();
}
@@ -30,6 +31,7 @@ Page_marker::mark_smob (SCM smob)
Page_marker *pm = (Page_marker *) SCM_CELL_WORD_1 (smob);
scm_gc_mark (pm->symbol_);
scm_gc_mark (pm->permission_);
+ scm_gc_mark (pm->label_);
return SCM_EOL;
}
@@ -53,3 +55,24 @@ Page_marker::permission_value ()
{
return permission_;
}
+
+SCM
+Page_marker::label ()
+{
+ return label_;
+}
+
+void
+Page_marker::set_permission (SCM symbol, SCM permission)
+{
+ symbol_ = symbol;
+ permission_ = permission;
+}
+
+void
+Page_marker::set_label (SCM label)
+{
+ label_ = label;
+}
+
+
diff --git a/lily/paper-book.cc b/lily/paper-book.cc
index 95be368..ec603e8 100644
--- a/lily/paper-book.cc
+++ b/lily/paper-book.cc
@@ -270,6 +270,19 @@ set_system_penalty (SCM sys, SCM header)
}
}
+void
+set_label (SCM sys, SCM label)
+{
+ if (Paper_score *ps = dynamic_cast<Paper_score*> (unsmob_music_output (sys)))
+ {
+ SCM labels = ps->layout ()->c_variable ("labels");
+ ps->layout ()->set_variable (ly_symbol2scm ("labels"),
+ scm_cons (label, labels));
+ }
+ else if (Prob *pb = unsmob_prob (sys))
+ pb->set_property ("labels", scm_cons (label, pb->get_property ("labels")));
+}
+
SCM
Paper_book::get_score_title (SCM header)
{
@@ -324,11 +337,22 @@ Paper_book::get_system_specs ()
}
else if (Page_marker *page_marker = unsmob_page_marker (scm_car (s)))
{
- /* a page marker: set previous element page break or turn permission
*/
- if (scm_is_pair (system_specs))
- set_page_permission (scm_car (system_specs),
- page_marker->permission_symbol (),
- page_marker->permission_value ());
+ /* page markers are used to set page breaking/tunrning permission,
+ or to place bookmarking labels */
+ if (scm_is_symbol (page_marker->permission_symbol ()))
+ {
+ /* set previous element page break or turn permission */
+ if (scm_is_pair (system_specs))
+ set_page_permission (scm_car (system_specs),
+ page_marker->permission_symbol (),
+ page_marker->permission_value ());
+ }
+ if (scm_is_symbol (page_marker->label ()))
+ {
+ /* set previous element label */
+ if (scm_is_pair (system_specs))
+ set_label (scm_car (system_specs), page_marker->label ());
+ }
}
else if (Music_output *mop = unsmob_music_output (scm_car (s)))
{
diff --git a/lily/stencil-interpret.cc b/lily/stencil-interpret.cc
index f6deee0..8afc330 100644
--- a/lily/stencil-interpret.cc
+++ b/lily/stencil-interpret.cc
@@ -21,6 +21,11 @@ interpret_stencil_expression (SCM expr,
SCM head = scm_car (expr);
+ if (head == ly_symbol2scm ("delay-stencil-evaluation"))
+ {
+ interpret_stencil_expression (scm_force (scm_cadr (expr)), func,
func_arg, o);
+ return;
+ }
if (head == ly_symbol2scm ("translate-stencil"))
{
o += ly_scm2offset (scm_cadr (expr));
diff --git a/lily/system.cc b/lily/system.cc
index e700615..7ba66a8 100644
--- a/lily/system.cc
+++ b/lily/system.cc
@@ -225,6 +225,13 @@ System::break_into_pieces (vector<Column
Interval iv (pure_height (this, st, end));
system->set_property ("pure-Y-extent", ly_interval2scm (iv));
+ /* set the first system labels with the score ones */
+ if (i == 0)
+ {
+ SCM labels = pscore_->layout ()->c_variable ("labels");
+ system->set_property ("labels", labels);
+ }
+
system->set_bound (LEFT, c[0]);
system->set_bound (RIGHT, c.back ());
for (vsize j = 0; j < c.size (); j++)
diff --git a/scm/define-markup-commands.scm b/scm/define-markup-commands.scm
index 8a0853e..d1f5dd0 100644
--- a/scm/define-markup-commands.scm
+++ b/scm/define-markup-commands.scm
@@ -1463,8 +1463,30 @@ that."
(m (interpret-markup layout props arg)))
(bracketify-stencil m Y th (* 2.5 th) th)))
-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; size indications arrow
+;; Delayed markup evaluation
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(define-builtin-markup-command (page-ref layout props label gauge default)
+ (symbol? markup? markup?)
+ "Reference to a page number. @var{label} is the label set on the referenced
+page (using the @code{\\label} command), @var{gauge} a markup used to estimate
+the maximum width of the page number, and @var{default} the value to display
+when @var{label} is not found."
+ (let* ((gauge-stencil (interpret-markup layout props gauge))
+ (x-ext (ly:stencil-extent gauge-stencil X))
+ (y-ext (ly:stencil-extent gauge-stencil Y)))
+ (ly:make-stencil
+ `(delay-stencil-evaluation
+ ,(delay (ly:stencil-expr
+ (let* ((table (ly:output-def-lookup layout 'label-page-table))
+ (label-page (and (list? table) (assoc label table)))
+ (page-number (and label-page (cdr label-page)))
+ (page-markup (if page-number (format "~a" page-number)
default))
+ (page-stencil (interpret-markup layout props
page-markup))
+ (gap (- (interval-length x-ext)
+ (interval-length (ly:stencil-extent page-stencil
X)))))
+ (interpret-markup layout props
+ (markup #:concat (#:hspace gap
page-markup)))))))
+ x-ext
+ y-ext)))
diff --git a/scm/define-stencil-commands.scm b/scm/define-stencil-commands.scm
index 9b0b942..6a027b6 100644
--- a/scm/define-stencil-commands.scm
+++ b/scm/define-stencil-commands.scm
@@ -37,6 +37,8 @@
no-origin
placebox
unknown
+
+ delay-stencil-evaluation
))
;; TODO:
diff --git a/scm/lily-library.scm b/scm/lily-library.scm
index 7a1141d..5435533 100644
--- a/scm/lily-library.scm
+++ b/scm/lily-library.scm
@@ -70,17 +70,21 @@
value
#f)))
(cond ((music-property 'page-marker)
- ;; a page marker: set page break/turn permissions
- (for-each (lambda (symbol)
- (let ((permission (music-property symbol)))
- (if (symbol? permission)
- (score-handler
- (ly:make-page-marker symbol
- (if (eqv? 'forbid permission)
- '()
- permission))))))
- (list 'line-break-permission 'page-break-permission
- 'page-turn-permission)))
+ ;; a page marker: set page break/turn permissions or label
+ (begin
+ (let ((label (music-property 'label)))
+ (if (symbol? label)
+ (score-handler (ly:make-page-label-marker label))))
+ (for-each (lambda (symbol)
+ (let ((permission (music-property symbol)))
+ (if (symbol? permission)
+ (score-handler
+ (ly:make-page-permission-marker symbol
+ (if (eqv? 'forbid
permission)
+ '()
+
permission))))))
+ (list 'line-break-permission 'page-break-permission
+ 'page-turn-permission))))
((not (music-property 'void))
;; a regular music expression: make a score with this music
;; void music is discarded
- [patch] \label, page references,
Nicolas Sceaux <=