]> git.donarmstrong.com Git - lilypond.git/blob - lily/pdf-scheme.cc
Issue 4550 (2/2) Avoid "using namespace std;" in included files
[lilypond.git] / lily / pdf-scheme.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 2011--2015 Reinhold Kainhofer <reinhold@kainhofer.com>
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 <glib.h>
21
22 #include "international.hh"
23 #include "warn.hh"
24 #include "lily-guile.hh"
25
26 LY_DEFINE (ly_encode_string_for_pdf, "ly:encode-string-for-pdf",
27            1, 0, 0, (SCM str),
28            "Encode the given string to either Latin1 (which is a subset of"
29            " the PDFDocEncoding) or if that's not possible to full UTF-16BE"
30            " with Byte-Order-Mark (BOM).")
31 {
32   LY_ASSERT_TYPE (scm_is_string, str, 1);
33   char *p = ly_scm2str0 (str);
34   char *g = NULL;
35   char const *charset = "UTF-8"; // Input is ALWAYS UTF-8!
36   gsize bytes_written = 0;
37
38 #if 0
39
40   /* First, try to convert to ISO-8859-1 (no encodings required). This will
41    * fail, if the string contains accented characters, so we do not check
42    * for errors. */
43   g = g_convert (p, -1, "ISO-8859-1", charset, 0, &bytes_written, 0);
44
45 #else
46
47   /* In contrast to the above comment, we do _not_ try full ISO-8859-1
48    * since a number of Ghostscript versions fail to properly convert
49    * this into PDF.  UTF-16BE, in contrast, works better with recent
50    * versions of Ghostscript.
51    */
52
53   g = g_convert (p, -1, "ASCII", charset, 0, &bytes_written, 0);
54
55 #endif
56
57   /* If that fails, we have to resolve to full UTF-16BE */
58   if (!g)
59     {
60       GError *e = NULL;
61       char *g_without_BOM = g_convert (p, -1, "UTF-16BE", charset, 0, &bytes_written, &e);
62       if (e != NULL)
63         {
64           warning (_f ("Conversion of string `%s' to UTF-16be failed: %s", p, e->message));
65           g_error_free (e);
66         }
67       /* UTF-16BE allows/recommends a byte-order-mark (BOM) of two bytes
68        * \xFE\xFF at the begin of the string. The pdfmark specification
69        * requires it and depends on it to distinguish PdfDocEncoding from
70        * UTF-16BE. As g_convert does not automatically prepend this BOM
71        * for UTF-16BE (only for UTF-16, which uses lower endian by default,
72        * though), we have to prepend it manually. */
73       if (g_without_BOM) // conversion to UTF-16be might have failed (shouldn't!)
74         {
75           g = (char *)malloc ( sizeof (char) * (bytes_written + 3));
76           char const *BOM = "\xFE\xFF";
77           strcpy (g, BOM);
78           memcpy (&g[2], g_without_BOM, bytes_written + 1); // Copy string + \0
79           g_free (g_without_BOM);
80           bytes_written += 2;
81         }
82     }
83   free (p);
84
85   /* Convert back to SCM object and return it */
86   /* FIXME guile-2.0: With guile 2.0 the internal representation of a string
87    *                  has changed (char vector rather than binary bytes in
88    *                  UTF-8). However, with guile 2.0, ly:encode-string-for-pdf
89    *                  is no longer needed and can be replaced by the new
90    *                  (string->utf16 str 'big)
91    */
92   if (g)
93     return scm_take_str (g, bytes_written); // scm_take_str eventually frees g!
94   else
95     return str;
96 }