Read UTF8 string lengths correctly when checking closed captions (part of #1446).
authorCarl Hetherington <cth@carlh.net>
Thu, 17 Jan 2019 22:33:55 +0000 (22:33 +0000)
committerCarl Hetherington <cth@carlh.net>
Thu, 17 Jan 2019 22:33:55 +0000 (22:33 +0000)
src/lib/hints.cc
src/lib/util.cc
src/lib/util.h
test/util_test.cc

index d961b1a3022eef80240db344623b3760064b3555..6238aa991b7e6a2550f4518109694c3e932edc70 100644 (file)
@@ -311,7 +311,7 @@ Hints::text (PlayerText text, TextType type, DCPTimePeriod period)
 
        int lines = text.string.size();
        BOOST_FOREACH (StringText i, text.string) {
-               if (i.text().length() > CLOSED_CAPTION_LENGTH) {
+               if (utf8_strlen(i.text()) > CLOSED_CAPTION_LENGTH) {
                        ++lines;
                        if (!_long_ccap) {
                                _long_ccap = true;
index 7472047e87b206003cfd367a3fdfc6ae2e1a2bfc..cd2d2e753b3827c74e6491c49583b2595c97ed7f 100644 (file)
@@ -815,6 +815,25 @@ checked_fread (void* ptr, size_t size, FILE* stream, boost::filesystem::path pat
        }
 }
 
+size_t
+utf8_strlen (string s)
+{
+       size_t const len = s.length ();
+       int N = 0;
+       for (size_t i = 0; i < len; ++i) {
+               unsigned char c = s[i];
+               if ((c & 0xe0) == 0xc0) {
+                       ++i;
+               } else if ((c & 0xf0) == 0xe0) {
+                       i += 2;
+               } else if ((c & 0xf8) == 0xf0) {
+                       i += 3;
+               }
+               ++N;
+       }
+       return N;
+}
+
 #ifdef DCPOMATIC_VARIANT_SWAROOP
 
 /* Make up a key from the machine UUID */
index bdf2480fcd5ae08bd9108f730421835a89072931..7c0eb4b6d475af23f134118e21a5aee2abebf206 100644 (file)
@@ -100,6 +100,7 @@ extern boost::shared_ptr<AudioBuffers> remap (boost::shared_ptr<const AudioBuffe
 extern Eyes increment_eyes (Eyes e);
 extern void checked_fread (void* ptr, size_t size, FILE* stream, boost::filesystem::path path);
 extern void checked_fwrite (void const * ptr, size_t size, FILE* stream, boost::filesystem::path path);
+extern size_t utf8_strlen (std::string s);
 #ifdef DCPOMATIC_VARIANT_SWAROOP
 extern boost::shared_ptr<dcp::CertificateChain> read_swaroop_chain (boost::filesystem::path path);
 extern void write_swaroop_chain (boost::shared_ptr<const dcp::CertificateChain> chain, boost::filesystem::path output);
index ba33b42c50ae9152cd53ad88c811dd39a19d6b47..d8cb61fdc30677d2208e52ca232554f60bd1762b 100644 (file)
@@ -92,6 +92,13 @@ BOOST_AUTO_TEST_CASE (tidy_for_filename_test)
        BOOST_CHECK_EQUAL (tidy_for_filename ("abcdefghï"), "abcdefghï");
 }
 
+BOOST_AUTO_TEST_CASE (utf8_strlen_test)
+{
+       BOOST_CHECK_EQUAL (utf8_strlen("hello world"), 11);
+       BOOST_CHECK_EQUAL (utf8_strlen("hëllo world"), 11);
+       BOOST_CHECK_EQUAL (utf8_strlen("hëłlo wørld"), 11);
+}
+
 #ifdef DCPOMATIC_VARIANT_SWAROOP
 BOOST_AUTO_TEST_CASE (swaroop_chain_test)
 {
@@ -111,5 +118,4 @@ BOOST_AUTO_TEST_CASE (swaroop_chain_test)
 
        BOOST_CHECK (cc->root_to_leaf() == back->root_to_leaf());
 }
-
 #endif