1 ////////////////////////////////////////////////////////////////////////////////
3 // Copyright 2015 - 2017, Paul Beckingham, Federico Hernandez.
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
12 // The above copyright notice and this permission notice shall be included
13 // in all copies or substantial portions of the Software.
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 // http://www.opensource.org/licenses/mit-license.php
25 ////////////////////////////////////////////////////////////////////////////////
28 #include <Composite.h>
33 ////////////////////////////////////////////////////////////////////////////////
34 // Initially assume no text, but infinite virtual space.
36 // Ã…llow overlay placement of arbitrary text at any offset, real or virtual, and
37 // using a specific color.
41 // c.add ("aaaaaaaaaa", 2, Color ("...")); // Layer 1
42 // c.add ("bbbbb", 5, Color ("...")); // Layer 2
43 // c.add ("c", 15, Color ("...")); // Layer 3
45 // _layers = { std::make_tuple ("aaaaaaaaaa", 2, Color ("...")),
46 // std::make_tuple ("bbbbb", 5, Color ("...")),
47 // std::make_tuple ("c", 15, Color ("..."))};
50 const std::string& text,
51 std::string::size_type offset,
54 _layers.push_back (std::make_tuple (text, offset, color));
57 ////////////////////////////////////////////////////////////////////////////////
58 // Merge the layers of text and color into one string.
62 // c.add ("aaaaaaaaaa", 2, Color ("...")); // Layer 1
63 // c.add ("bbbbb", 5, Color ("...")); // Layer 2
64 // c.add ("c", 15, Color ("...")); // Layer 3
66 // _layers = { std::make_tuple ("aaaaaaaaaa", 2, Color ("...")),
67 // std::make_tuple ("bbbbb", 5, Color ("...")),
68 // std::make_tuple ("c", 15, Color ("..."))};
70 // Arrange strings conceptually:
72 // 0123456789012345 // Position
74 // aaaaaaaaaa // Layer 1
78 // Walk all strings left to right, selecting the character and color from the
79 // highest numbered layer. Emit color codes only on edge detection.
81 std::string Composite::str () const
83 // The strings are broken into a vector of int, for UTF8 support.
84 std::vector <int> characters;
85 std::vector <int> colors;
86 for (unsigned int layer = 0; layer < _layers.size (); ++layer)
88 auto text = std::get <0> (_layers[layer]);
89 auto offset = std::get <1> (_layers[layer]);
90 auto len = utf8_text_length (text);
92 // Make sure the vectors are large enough to support a write operator[].
93 if (characters.size () < offset + len)
95 characters.resize (offset + len, 32);
96 colors.resize (offset + len, 0);
99 // Copy in the layer characters and color indexes.
100 std::string::size_type cursor = 0;
103 while ((character = utf8_next_char (text, cursor)))
105 characters[offset + count] = character;
106 colors [offset + count] = layer + 1;
111 // Now walk the character and color vector, emitting every character and
112 // every detected color change.
113 std::stringstream out;
115 for (unsigned int i = 0; i < characters.size (); ++i)
117 // A change in color triggers a code emit.
118 if (prev_color != colors[i])
121 out << std::get <2> (_layers[prev_color - 1]).end ();
124 out << std::get <2> (_layers[colors[i] - 1]).code ();
126 out << std::get <2> (_layers[prev_color - 1]).end ();
128 prev_color = colors[i];
131 out << utf8_character (characters[i]);
134 // Terminate the color codes, if necessary.
136 out << std::get <2> (_layers[prev_color - 1]).end ();
141 ////////////////////////////////////////////////////////////////////////////////
142 // So the same instance can be reused.
143 void Composite::clear ()
148 ////////////////////////////////////////////////////////////////////////////////