Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: MaximInterface
Text.cpp@0:33d4e66780c0, 2017-02-24 (annotated)
- Committer:
- IanBenzMaxim
- Date:
- Fri Feb 24 11:23:12 2017 -0600
- Revision:
- 0:33d4e66780c0
- Child:
- 3:d2799d8497c0
Initial commit.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
IanBenzMaxim | 0:33d4e66780c0 | 1 | /******************************************************************************* |
IanBenzMaxim | 0:33d4e66780c0 | 2 | * Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. |
IanBenzMaxim | 0:33d4e66780c0 | 3 | * |
IanBenzMaxim | 0:33d4e66780c0 | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
IanBenzMaxim | 0:33d4e66780c0 | 5 | * copy of this software and associated documentation files (the "Software"), |
IanBenzMaxim | 0:33d4e66780c0 | 6 | * to deal in the Software without restriction, including without limitation |
IanBenzMaxim | 0:33d4e66780c0 | 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
IanBenzMaxim | 0:33d4e66780c0 | 8 | * and/or sell copies of the Software, and to permit persons to whom the |
IanBenzMaxim | 0:33d4e66780c0 | 9 | * Software is furnished to do so, subject to the following conditions: |
IanBenzMaxim | 0:33d4e66780c0 | 10 | * |
IanBenzMaxim | 0:33d4e66780c0 | 11 | * The above copyright notice and this permission notice shall be included |
IanBenzMaxim | 0:33d4e66780c0 | 12 | * in all copies or substantial portions of the Software. |
IanBenzMaxim | 0:33d4e66780c0 | 13 | * |
IanBenzMaxim | 0:33d4e66780c0 | 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
IanBenzMaxim | 0:33d4e66780c0 | 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
IanBenzMaxim | 0:33d4e66780c0 | 16 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
IanBenzMaxim | 0:33d4e66780c0 | 17 | * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES |
IanBenzMaxim | 0:33d4e66780c0 | 18 | * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
IanBenzMaxim | 0:33d4e66780c0 | 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
IanBenzMaxim | 0:33d4e66780c0 | 20 | * OTHER DEALINGS IN THE SOFTWARE. |
IanBenzMaxim | 0:33d4e66780c0 | 21 | * |
IanBenzMaxim | 0:33d4e66780c0 | 22 | * Except as contained in this notice, the name of Maxim Integrated |
IanBenzMaxim | 0:33d4e66780c0 | 23 | * Products, Inc. shall not be used except as stated in the Maxim Integrated |
IanBenzMaxim | 0:33d4e66780c0 | 24 | * Products, Inc. Branding Policy. |
IanBenzMaxim | 0:33d4e66780c0 | 25 | * |
IanBenzMaxim | 0:33d4e66780c0 | 26 | * The mere transfer of this software does not imply any licenses |
IanBenzMaxim | 0:33d4e66780c0 | 27 | * of trade secrets, proprietary technology, copyrights, patents, |
IanBenzMaxim | 0:33d4e66780c0 | 28 | * trademarks, maskwork rights, or any other form of intellectual |
IanBenzMaxim | 0:33d4e66780c0 | 29 | * property whatsoever. Maxim Integrated Products, Inc. retains all |
IanBenzMaxim | 0:33d4e66780c0 | 30 | * ownership rights. |
IanBenzMaxim | 0:33d4e66780c0 | 31 | *******************************************************************************/ |
IanBenzMaxim | 0:33d4e66780c0 | 32 | |
IanBenzMaxim | 0:33d4e66780c0 | 33 | #include <algorithm> |
IanBenzMaxim | 0:33d4e66780c0 | 34 | #include <functional> |
IanBenzMaxim | 0:33d4e66780c0 | 35 | #include <list> |
IanBenzMaxim | 0:33d4e66780c0 | 36 | #include "Bitmap.hpp" |
IanBenzMaxim | 0:33d4e66780c0 | 37 | #include "Display.hpp" |
IanBenzMaxim | 0:33d4e66780c0 | 38 | #include "Text.hpp" |
IanBenzMaxim | 0:33d4e66780c0 | 39 | |
IanBenzMaxim | 0:33d4e66780c0 | 40 | using std::string; |
IanBenzMaxim | 0:33d4e66780c0 | 41 | |
IanBenzMaxim | 0:33d4e66780c0 | 42 | static const unsigned int characterWidth = 5; |
IanBenzMaxim | 0:33d4e66780c0 | 43 | static const unsigned int characterHeight = 7; |
IanBenzMaxim | 0:33d4e66780c0 | 44 | |
IanBenzMaxim | 0:33d4e66780c0 | 45 | static const unsigned char printableCharBegin = 0x20; |
IanBenzMaxim | 0:33d4e66780c0 | 46 | static const unsigned char printableCharEnd = 0x7E; |
IanBenzMaxim | 0:33d4e66780c0 | 47 | |
IanBenzMaxim | 0:33d4e66780c0 | 48 | static const uint8_t characterMap[][characterWidth] = { |
IanBenzMaxim | 0:33d4e66780c0 | 49 | { 0x00, 0x00, 0x00, 0x00, 0x00 }, // ' ' |
IanBenzMaxim | 0:33d4e66780c0 | 50 | { 0x00, 0x00, 0xF2, 0x00, 0x00 }, // '!' |
IanBenzMaxim | 0:33d4e66780c0 | 51 | { 0x00, 0xE0, 0x00, 0xE0, 0x00 }, // '"' |
IanBenzMaxim | 0:33d4e66780c0 | 52 | { 0x28, 0xFE, 0x28, 0xFE, 0x28 }, // '#' |
IanBenzMaxim | 0:33d4e66780c0 | 53 | { 0x24, 0x54, 0xFE, 0x54, 0x48 }, // '$' |
IanBenzMaxim | 0:33d4e66780c0 | 54 | { 0xC4, 0xC8, 0x10, 0x26, 0x46 }, // '%' |
IanBenzMaxim | 0:33d4e66780c0 | 55 | { 0x6C, 0x92, 0xAA, 0x44, 0x0A }, // '&' |
IanBenzMaxim | 0:33d4e66780c0 | 56 | { 0x00, 0xA0, 0xC0, 0x00, 0x00 }, // ''' |
IanBenzMaxim | 0:33d4e66780c0 | 57 | { 0x00, 0x28, 0x44, 0x82, 0x00 }, // '(' |
IanBenzMaxim | 0:33d4e66780c0 | 58 | { 0x00, 0x82, 0x44, 0x38, 0x00 }, // ')' |
IanBenzMaxim | 0:33d4e66780c0 | 59 | { 0x28, 0x10, 0x7C, 0x10, 0x28 }, // '*' |
IanBenzMaxim | 0:33d4e66780c0 | 60 | { 0x10, 0x10, 0x7C, 0x10, 0x10 }, // '+' |
IanBenzMaxim | 0:33d4e66780c0 | 61 | { 0x00, 0x0A, 0x0C, 0x00, 0x00 }, // ',' |
IanBenzMaxim | 0:33d4e66780c0 | 62 | { 0x10, 0x10, 0x10, 0x10, 0x10 }, // '-' |
IanBenzMaxim | 0:33d4e66780c0 | 63 | { 0x00, 0x06, 0x06, 0x00, 0x00 }, // '.' |
IanBenzMaxim | 0:33d4e66780c0 | 64 | { 0x04, 0x08, 0x10, 0x20, 0x40 }, // '/' |
IanBenzMaxim | 0:33d4e66780c0 | 65 | { 0x7C, 0x8A, 0x92, 0xA2, 0x7C }, // '0' |
IanBenzMaxim | 0:33d4e66780c0 | 66 | { 0x00, 0x42, 0xFE, 0x02, 0x00 }, // '1' |
IanBenzMaxim | 0:33d4e66780c0 | 67 | { 0x42, 0x86, 0x8A, 0x92, 0x62 }, // '2' |
IanBenzMaxim | 0:33d4e66780c0 | 68 | { 0x84, 0x82, 0xA2, 0xD2, 0x8C }, // '3' |
IanBenzMaxim | 0:33d4e66780c0 | 69 | { 0x18, 0x28, 0x48, 0xFE, 0x08 }, // '4' |
IanBenzMaxim | 0:33d4e66780c0 | 70 | { 0xE4, 0xA2, 0xA2, 0xA2, 0x9C }, // '5' |
IanBenzMaxim | 0:33d4e66780c0 | 71 | { 0x3C, 0x52, 0x92, 0x92, 0x0C }, // '6' |
IanBenzMaxim | 0:33d4e66780c0 | 72 | { 0x80, 0x8E, 0x90, 0xA0, 0xC0 }, // '7' |
IanBenzMaxim | 0:33d4e66780c0 | 73 | { 0x6C, 0x92, 0x92, 0x92, 0x6C }, // '8' |
IanBenzMaxim | 0:33d4e66780c0 | 74 | { 0x60, 0x92, 0x92, 0x94, 0x78 }, // '9' |
IanBenzMaxim | 0:33d4e66780c0 | 75 | { 0x00, 0x6C, 0x6C, 0x00, 0x00 }, // ':' |
IanBenzMaxim | 0:33d4e66780c0 | 76 | { 0x00, 0x6A, 0x6C, 0x00, 0x00 }, // ';' |
IanBenzMaxim | 0:33d4e66780c0 | 77 | { 0x10, 0x28, 0x44, 0x82, 0x00 }, // '<' |
IanBenzMaxim | 0:33d4e66780c0 | 78 | { 0x28, 0x28, 0x28, 0x28, 0x28 }, // '=' |
IanBenzMaxim | 0:33d4e66780c0 | 79 | { 0x00, 0x82, 0x44, 0x28, 0x10 }, // '>' |
IanBenzMaxim | 0:33d4e66780c0 | 80 | { 0x40, 0x80, 0x8A, 0x90, 0x60 }, // '?' |
IanBenzMaxim | 0:33d4e66780c0 | 81 | { 0x4C, 0x92, 0x9E, 0x82, 0x7C }, // '@' |
IanBenzMaxim | 0:33d4e66780c0 | 82 | { 0x7E, 0x88, 0x88, 0x88, 0x7E }, // 'A' |
IanBenzMaxim | 0:33d4e66780c0 | 83 | { 0xFE, 0x92, 0x92, 0x92, 0x6C }, // 'B' |
IanBenzMaxim | 0:33d4e66780c0 | 84 | { 0x7C, 0x82, 0x82, 0x82, 0x44 }, // 'C' |
IanBenzMaxim | 0:33d4e66780c0 | 85 | { 0xFE, 0x82, 0x82, 0x44, 0x38 }, // 'D' |
IanBenzMaxim | 0:33d4e66780c0 | 86 | { 0xFE, 0x92, 0x92, 0x92, 0x82 }, // 'E' |
IanBenzMaxim | 0:33d4e66780c0 | 87 | { 0xFE, 0x90, 0x90, 0x90, 0x80 }, // 'F' |
IanBenzMaxim | 0:33d4e66780c0 | 88 | { 0x7C, 0x82, 0x92, 0x92, 0x5E }, // 'G' |
IanBenzMaxim | 0:33d4e66780c0 | 89 | { 0xFE, 0x10, 0x10, 0x10, 0xFE }, // 'H' |
IanBenzMaxim | 0:33d4e66780c0 | 90 | { 0x00, 0x82, 0xFE, 0x82, 0x00 }, // 'I' |
IanBenzMaxim | 0:33d4e66780c0 | 91 | { 0x04, 0x02, 0x82, 0xFC, 0x80 }, // 'J' |
IanBenzMaxim | 0:33d4e66780c0 | 92 | { 0xFE, 0x10, 0x28, 0x44, 0x82 }, // 'K' |
IanBenzMaxim | 0:33d4e66780c0 | 93 | { 0xFE, 0x02, 0x02, 0x02, 0x02 }, // 'L' |
IanBenzMaxim | 0:33d4e66780c0 | 94 | { 0xFE, 0x40, 0x21, 0x40, 0xFE }, // 'M' |
IanBenzMaxim | 0:33d4e66780c0 | 95 | { 0xFE, 0x20, 0x10, 0x08, 0xFE }, // 'N' |
IanBenzMaxim | 0:33d4e66780c0 | 96 | { 0x7C, 0x82, 0x82, 0x82, 0x7C }, // 'O' |
IanBenzMaxim | 0:33d4e66780c0 | 97 | { 0xFE, 0x90, 0x90, 0x90, 0x60 }, // 'P' |
IanBenzMaxim | 0:33d4e66780c0 | 98 | { 0x7C, 0x82, 0x8A, 0x82, 0x7A }, // 'Q' |
IanBenzMaxim | 0:33d4e66780c0 | 99 | { 0xFE, 0x90, 0x98, 0x94, 0x62 }, // 'R' |
IanBenzMaxim | 0:33d4e66780c0 | 100 | { 0x62, 0x92, 0x92, 0x92, 0x8C }, // 'S' |
IanBenzMaxim | 0:33d4e66780c0 | 101 | { 0x80, 0x80, 0xFE, 0x80, 0x80 }, // 'T' |
IanBenzMaxim | 0:33d4e66780c0 | 102 | { 0xFC, 0x02, 0x02, 0x02, 0xFC }, // 'U' |
IanBenzMaxim | 0:33d4e66780c0 | 103 | { 0xF8, 0x04, 0x02, 0x04, 0xF8 }, // 'V' |
IanBenzMaxim | 0:33d4e66780c0 | 104 | { 0xFC, 0x02, 0x1C, 0x02, 0xFC }, // 'W' |
IanBenzMaxim | 0:33d4e66780c0 | 105 | { 0xC6, 0x28, 0x10, 0x28, 0xC6 }, // 'X' |
IanBenzMaxim | 0:33d4e66780c0 | 106 | { 0xF0, 0x10, 0x0F, 0x10, 0xF0 }, // 'Y' |
IanBenzMaxim | 0:33d4e66780c0 | 107 | { 0x86, 0x8A, 0x92, 0xA2, 0xC2 }, // 'Z' |
IanBenzMaxim | 0:33d4e66780c0 | 108 | { 0x00, 0xFE, 0x82, 0x82, 0x00 }, // '[' |
IanBenzMaxim | 0:33d4e66780c0 | 109 | { 0x40, 0x20, 0x10, 0x08, 0x04 }, // '\' |
IanBenzMaxim | 0:33d4e66780c0 | 110 | { 0x00, 0x82, 0x82, 0xFE, 0x00 }, // ']' |
IanBenzMaxim | 0:33d4e66780c0 | 111 | { 0x20, 0x40, 0x80, 0x40, 0x20 }, // '^' |
IanBenzMaxim | 0:33d4e66780c0 | 112 | { 0x02, 0x02, 0x02, 0x02, 0x02 }, // '_' |
IanBenzMaxim | 0:33d4e66780c0 | 113 | { 0x00, 0x80, 0x40, 0x20, 0x00 }, // '`' |
IanBenzMaxim | 0:33d4e66780c0 | 114 | { 0x04, 0x2A, 0x2A, 0x2A, 0x1E }, // 'a' |
IanBenzMaxim | 0:33d4e66780c0 | 115 | { 0xFE, 0x12, 0x22, 0x22, 0x1C }, // 'b' |
IanBenzMaxim | 0:33d4e66780c0 | 116 | { 0x1C, 0x22, 0x22, 0x22, 0x04 }, // 'c' |
IanBenzMaxim | 0:33d4e66780c0 | 117 | { 0x1C, 0x22, 0x22, 0x12, 0xFE }, // 'd' |
IanBenzMaxim | 0:33d4e66780c0 | 118 | { 0x1C, 0x2A, 0x2A, 0x2A, 0x18 }, // 'e' |
IanBenzMaxim | 0:33d4e66780c0 | 119 | { 0x10, 0x7E, 0x90, 0x80, 0x40 }, // 'f' |
IanBenzMaxim | 0:33d4e66780c0 | 120 | { 0x30, 0x4A, 0x4A, 0x4A, 0x7C }, // 'g' |
IanBenzMaxim | 0:33d4e66780c0 | 121 | { 0xFE, 0x10, 0x20, 0x20, 0x1E }, // 'h' |
IanBenzMaxim | 0:33d4e66780c0 | 122 | { 0x00, 0x22, 0xBE, 0x02, 0x00 }, // 'i' |
IanBenzMaxim | 0:33d4e66780c0 | 123 | { 0x04, 0x02, 0x22, 0xBC, 0x00 }, // 'j' |
IanBenzMaxim | 0:33d4e66780c0 | 124 | { 0xFE, 0x08, 0x14, 0x22, 0x00 }, // 'k' |
IanBenzMaxim | 0:33d4e66780c0 | 125 | { 0x00, 0x82, 0xFE, 0x02, 0x00 }, // 'l' |
IanBenzMaxim | 0:33d4e66780c0 | 126 | { 0x3E, 0x20, 0x18, 0x20, 0x1E }, // 'm' |
IanBenzMaxim | 0:33d4e66780c0 | 127 | { 0x3E, 0x10, 0x20, 0x20, 0x1E }, // 'n' |
IanBenzMaxim | 0:33d4e66780c0 | 128 | { 0x1C, 0x22, 0x22, 0x22, 0x1C }, // 'o' |
IanBenzMaxim | 0:33d4e66780c0 | 129 | { 0x3E, 0x28, 0x28, 0x28, 0x10 }, // 'p' |
IanBenzMaxim | 0:33d4e66780c0 | 130 | { 0x10, 0x28, 0x28, 0x18, 0x3E }, // 'q' |
IanBenzMaxim | 0:33d4e66780c0 | 131 | { 0x3E, 0x10, 0x20, 0x20, 0x10 }, // 'r' |
IanBenzMaxim | 0:33d4e66780c0 | 132 | { 0x12, 0x2A, 0x2A, 0x2A, 0x04 }, // 's' |
IanBenzMaxim | 0:33d4e66780c0 | 133 | { 0x20, 0xFC, 0x22, 0x02, 0x04 }, // 't' |
IanBenzMaxim | 0:33d4e66780c0 | 134 | { 0x3C, 0x02, 0x02, 0x04, 0x3E }, // 'u' |
IanBenzMaxim | 0:33d4e66780c0 | 135 | { 0x38, 0x04, 0x02, 0x04, 0x38 }, // 'v' |
IanBenzMaxim | 0:33d4e66780c0 | 136 | { 0x3C, 0x02, 0x0C, 0x02, 0x3C }, // 'w' |
IanBenzMaxim | 0:33d4e66780c0 | 137 | { 0x22, 0x14, 0x08, 0x14, 0x22 }, // 'x' |
IanBenzMaxim | 0:33d4e66780c0 | 138 | { 0x30, 0x0A, 0x0A, 0x0A, 0x3C }, // 'y' |
IanBenzMaxim | 0:33d4e66780c0 | 139 | { 0x22, 0x26, 0x2A, 0x32, 0x22 }, // 'z' |
IanBenzMaxim | 0:33d4e66780c0 | 140 | { 0x00, 0x10, 0x6C, 0x82, 0x00 }, // '{' |
IanBenzMaxim | 0:33d4e66780c0 | 141 | { 0x00, 0x00, 0xFE, 0x00, 0x00 }, // '|' |
IanBenzMaxim | 0:33d4e66780c0 | 142 | { 0x00, 0x82, 0x6C, 0x10, 0x00 }, // '}' |
IanBenzMaxim | 0:33d4e66780c0 | 143 | { 0x10, 0x20, 0x10, 0x08, 0x10 } // '~' |
IanBenzMaxim | 0:33d4e66780c0 | 144 | }; |
IanBenzMaxim | 0:33d4e66780c0 | 145 | |
IanBenzMaxim | 0:33d4e66780c0 | 146 | static bool charPrintable(unsigned char c) |
IanBenzMaxim | 0:33d4e66780c0 | 147 | { |
IanBenzMaxim | 0:33d4e66780c0 | 148 | return (c >= printableCharBegin) && (c <= printableCharEnd); |
IanBenzMaxim | 0:33d4e66780c0 | 149 | } |
IanBenzMaxim | 0:33d4e66780c0 | 150 | |
IanBenzMaxim | 0:33d4e66780c0 | 151 | static void removeNonprintableChars(string & s) |
IanBenzMaxim | 0:33d4e66780c0 | 152 | { |
IanBenzMaxim | 0:33d4e66780c0 | 153 | s.erase(std::remove_if(s.begin(), s.end(), std::not1(std::ptr_fun(charPrintable)))); |
IanBenzMaxim | 0:33d4e66780c0 | 154 | } |
IanBenzMaxim | 0:33d4e66780c0 | 155 | |
IanBenzMaxim | 0:33d4e66780c0 | 156 | static bool compareStringLength(const string & a, const string & b) |
IanBenzMaxim | 0:33d4e66780c0 | 157 | { |
IanBenzMaxim | 0:33d4e66780c0 | 158 | return a.length() < b.length(); |
IanBenzMaxim | 0:33d4e66780c0 | 159 | } |
IanBenzMaxim | 0:33d4e66780c0 | 160 | |
IanBenzMaxim | 0:33d4e66780c0 | 161 | // Functor trims string if it exceeds a certain length. |
IanBenzMaxim | 0:33d4e66780c0 | 162 | class TrimString |
IanBenzMaxim | 0:33d4e66780c0 | 163 | { |
IanBenzMaxim | 0:33d4e66780c0 | 164 | public: |
IanBenzMaxim | 0:33d4e66780c0 | 165 | TrimString(string::size_type maxSize) : maxSize(maxSize) { } |
IanBenzMaxim | 0:33d4e66780c0 | 166 | |
IanBenzMaxim | 0:33d4e66780c0 | 167 | void operator()(string & s) |
IanBenzMaxim | 0:33d4e66780c0 | 168 | { |
IanBenzMaxim | 0:33d4e66780c0 | 169 | if (s.size() > maxSize) |
IanBenzMaxim | 0:33d4e66780c0 | 170 | { |
IanBenzMaxim | 0:33d4e66780c0 | 171 | s.resize(maxSize); |
IanBenzMaxim | 0:33d4e66780c0 | 172 | } |
IanBenzMaxim | 0:33d4e66780c0 | 173 | } |
IanBenzMaxim | 0:33d4e66780c0 | 174 | |
IanBenzMaxim | 0:33d4e66780c0 | 175 | private: |
IanBenzMaxim | 0:33d4e66780c0 | 176 | string::size_type maxSize; |
IanBenzMaxim | 0:33d4e66780c0 | 177 | }; |
IanBenzMaxim | 0:33d4e66780c0 | 178 | |
IanBenzMaxim | 0:33d4e66780c0 | 179 | // Split a string based on a character token. Token will be removed. |
IanBenzMaxim | 0:33d4e66780c0 | 180 | static std::list<string> tokenizeString(const string & toSplit, char token) |
IanBenzMaxim | 0:33d4e66780c0 | 181 | { |
IanBenzMaxim | 0:33d4e66780c0 | 182 | std::list<string> toSplitLines; |
IanBenzMaxim | 0:33d4e66780c0 | 183 | string::size_type beginIdx = 0, endIdx; |
IanBenzMaxim | 0:33d4e66780c0 | 184 | do |
IanBenzMaxim | 0:33d4e66780c0 | 185 | { |
IanBenzMaxim | 0:33d4e66780c0 | 186 | endIdx = toSplit.find(token, beginIdx); |
IanBenzMaxim | 0:33d4e66780c0 | 187 | toSplitLines.push_back(toSplit.substr(beginIdx, endIdx == string::npos ? string::npos : endIdx - beginIdx)); |
IanBenzMaxim | 0:33d4e66780c0 | 188 | beginIdx = endIdx + 1; |
IanBenzMaxim | 0:33d4e66780c0 | 189 | } while (endIdx != string::npos); |
IanBenzMaxim | 0:33d4e66780c0 | 190 | return toSplitLines; |
IanBenzMaxim | 0:33d4e66780c0 | 191 | } |
IanBenzMaxim | 0:33d4e66780c0 | 192 | |
IanBenzMaxim | 0:33d4e66780c0 | 193 | // Word wrap string into lines based on a specified line length. |
IanBenzMaxim | 0:33d4e66780c0 | 194 | static std::list<string> wrapLines(const string & toSplit, const string::size_type lineLen) |
IanBenzMaxim | 0:33d4e66780c0 | 195 | { |
IanBenzMaxim | 0:33d4e66780c0 | 196 | std::list<string> toSplitLines; |
IanBenzMaxim | 0:33d4e66780c0 | 197 | string::size_type beginIdx = 0; |
IanBenzMaxim | 0:33d4e66780c0 | 198 | if (lineLen > 0) |
IanBenzMaxim | 0:33d4e66780c0 | 199 | { |
IanBenzMaxim | 0:33d4e66780c0 | 200 | // Split lines as much as necessary. |
IanBenzMaxim | 0:33d4e66780c0 | 201 | string::size_type endIdx = lineLen; |
IanBenzMaxim | 0:33d4e66780c0 | 202 | while (((toSplit.length() - beginIdx) > lineLen) && (endIdx != string::npos)) |
IanBenzMaxim | 0:33d4e66780c0 | 203 | { |
IanBenzMaxim | 0:33d4e66780c0 | 204 | endIdx = toSplit.rfind(' ', endIdx); |
IanBenzMaxim | 0:33d4e66780c0 | 205 | if ((endIdx == string::npos) || (endIdx <= beginIdx)) |
IanBenzMaxim | 0:33d4e66780c0 | 206 | { |
IanBenzMaxim | 0:33d4e66780c0 | 207 | // Current word is too long to split. Find end of current word. |
IanBenzMaxim | 0:33d4e66780c0 | 208 | endIdx = toSplit.find(' ', beginIdx); |
IanBenzMaxim | 0:33d4e66780c0 | 209 | } |
IanBenzMaxim | 0:33d4e66780c0 | 210 | if (endIdx != string::npos) |
IanBenzMaxim | 0:33d4e66780c0 | 211 | { |
IanBenzMaxim | 0:33d4e66780c0 | 212 | toSplitLines.push_back(toSplit.substr(beginIdx, endIdx - beginIdx)); |
IanBenzMaxim | 0:33d4e66780c0 | 213 | beginIdx = endIdx + 1; |
IanBenzMaxim | 0:33d4e66780c0 | 214 | endIdx = beginIdx + lineLen; |
IanBenzMaxim | 0:33d4e66780c0 | 215 | } |
IanBenzMaxim | 0:33d4e66780c0 | 216 | } |
IanBenzMaxim | 0:33d4e66780c0 | 217 | } |
IanBenzMaxim | 0:33d4e66780c0 | 218 | // Last line is any remaining characters. |
IanBenzMaxim | 0:33d4e66780c0 | 219 | toSplitLines.push_back(toSplit.substr(beginIdx, toSplit.length() - beginIdx)); |
IanBenzMaxim | 0:33d4e66780c0 | 220 | return toSplitLines; |
IanBenzMaxim | 0:33d4e66780c0 | 221 | } |
IanBenzMaxim | 0:33d4e66780c0 | 222 | |
IanBenzMaxim | 0:33d4e66780c0 | 223 | Text::Text(const string & text, Graphic * parent) : |
IanBenzMaxim | 0:33d4e66780c0 | 224 | Graphic(parent), m_text(text), m_wordWrap(false), m_charSpacing(1), m_lineSpacing(1), |
IanBenzMaxim | 0:33d4e66780c0 | 225 | m_textLines(), m_preferredWidth(0), m_preferredHeight(0) |
IanBenzMaxim | 0:33d4e66780c0 | 226 | { |
IanBenzMaxim | 0:33d4e66780c0 | 227 | // Default to the preferred width and height. |
IanBenzMaxim | 0:33d4e66780c0 | 228 | update(); |
IanBenzMaxim | 0:33d4e66780c0 | 229 | setWidth(preferredWidth()); |
IanBenzMaxim | 0:33d4e66780c0 | 230 | setHeight(preferredHeight()); |
IanBenzMaxim | 0:33d4e66780c0 | 231 | } |
IanBenzMaxim | 0:33d4e66780c0 | 232 | |
IanBenzMaxim | 0:33d4e66780c0 | 233 | void Text::setText(const std::string & text) |
IanBenzMaxim | 0:33d4e66780c0 | 234 | { |
IanBenzMaxim | 0:33d4e66780c0 | 235 | if (m_text != text) |
IanBenzMaxim | 0:33d4e66780c0 | 236 | { |
IanBenzMaxim | 0:33d4e66780c0 | 237 | m_text = text; |
IanBenzMaxim | 0:33d4e66780c0 | 238 | invalidateRegion(); |
IanBenzMaxim | 0:33d4e66780c0 | 239 | } |
IanBenzMaxim | 0:33d4e66780c0 | 240 | } |
IanBenzMaxim | 0:33d4e66780c0 | 241 | |
IanBenzMaxim | 0:33d4e66780c0 | 242 | void Text::setWordWrap(bool wordWrap) |
IanBenzMaxim | 0:33d4e66780c0 | 243 | { |
IanBenzMaxim | 0:33d4e66780c0 | 244 | if (m_wordWrap != wordWrap) |
IanBenzMaxim | 0:33d4e66780c0 | 245 | { |
IanBenzMaxim | 0:33d4e66780c0 | 246 | m_wordWrap = wordWrap; |
IanBenzMaxim | 0:33d4e66780c0 | 247 | invalidateRegion(); |
IanBenzMaxim | 0:33d4e66780c0 | 248 | } |
IanBenzMaxim | 0:33d4e66780c0 | 249 | } |
IanBenzMaxim | 0:33d4e66780c0 | 250 | |
IanBenzMaxim | 0:33d4e66780c0 | 251 | void Text::setLineSpacing(unsigned int lineSpacing) |
IanBenzMaxim | 0:33d4e66780c0 | 252 | { |
IanBenzMaxim | 0:33d4e66780c0 | 253 | if (m_lineSpacing != lineSpacing) |
IanBenzMaxim | 0:33d4e66780c0 | 254 | { |
IanBenzMaxim | 0:33d4e66780c0 | 255 | m_lineSpacing = lineSpacing; |
IanBenzMaxim | 0:33d4e66780c0 | 256 | invalidateRegion(); |
IanBenzMaxim | 0:33d4e66780c0 | 257 | } |
IanBenzMaxim | 0:33d4e66780c0 | 258 | } |
IanBenzMaxim | 0:33d4e66780c0 | 259 | |
IanBenzMaxim | 0:33d4e66780c0 | 260 | void Text::setCharSpacing(unsigned int charSpacing) |
IanBenzMaxim | 0:33d4e66780c0 | 261 | { |
IanBenzMaxim | 0:33d4e66780c0 | 262 | if (m_charSpacing != charSpacing) |
IanBenzMaxim | 0:33d4e66780c0 | 263 | { |
IanBenzMaxim | 0:33d4e66780c0 | 264 | m_charSpacing = charSpacing; |
IanBenzMaxim | 0:33d4e66780c0 | 265 | invalidateRegion(); |
IanBenzMaxim | 0:33d4e66780c0 | 266 | } |
IanBenzMaxim | 0:33d4e66780c0 | 267 | } |
IanBenzMaxim | 0:33d4e66780c0 | 268 | |
IanBenzMaxim | 0:33d4e66780c0 | 269 | void Text::doPostLayout() |
IanBenzMaxim | 0:33d4e66780c0 | 270 | { |
IanBenzMaxim | 0:33d4e66780c0 | 271 | using std::list; |
IanBenzMaxim | 0:33d4e66780c0 | 272 | |
IanBenzMaxim | 0:33d4e66780c0 | 273 | if (regionValid()) |
IanBenzMaxim | 0:33d4e66780c0 | 274 | return; |
IanBenzMaxim | 0:33d4e66780c0 | 275 | |
IanBenzMaxim | 0:33d4e66780c0 | 276 | // Split string into lines. |
IanBenzMaxim | 0:33d4e66780c0 | 277 | m_textLines = tokenizeString(m_text, '\n'); |
IanBenzMaxim | 0:33d4e66780c0 | 278 | |
IanBenzMaxim | 0:33d4e66780c0 | 279 | // Remove non-printable characters. |
IanBenzMaxim | 0:33d4e66780c0 | 280 | std::for_each(m_textLines.begin(), m_textLines.end(), removeNonprintableChars); |
IanBenzMaxim | 0:33d4e66780c0 | 281 | |
IanBenzMaxim | 0:33d4e66780c0 | 282 | const unsigned int lineLen = |
IanBenzMaxim | 0:33d4e66780c0 | 283 | (width() / (characterWidth + m_charSpacing)) + |
IanBenzMaxim | 0:33d4e66780c0 | 284 | (((width() % (characterWidth + m_charSpacing)) >= characterWidth) ? 1 : 0); |
IanBenzMaxim | 0:33d4e66780c0 | 285 | const unsigned int numLines = |
IanBenzMaxim | 0:33d4e66780c0 | 286 | (height() / (characterHeight + m_lineSpacing)) + |
IanBenzMaxim | 0:33d4e66780c0 | 287 | (((height() % (characterHeight + m_lineSpacing)) >= characterHeight) ? 1 : 0); |
IanBenzMaxim | 0:33d4e66780c0 | 288 | |
IanBenzMaxim | 0:33d4e66780c0 | 289 | // Word wrap lines if enabled. |
IanBenzMaxim | 0:33d4e66780c0 | 290 | if (m_wordWrap) |
IanBenzMaxim | 0:33d4e66780c0 | 291 | { |
IanBenzMaxim | 0:33d4e66780c0 | 292 | list<string>::iterator lineIt = m_textLines.begin(); |
IanBenzMaxim | 0:33d4e66780c0 | 293 | while (lineIt != m_textLines.end()) |
IanBenzMaxim | 0:33d4e66780c0 | 294 | { |
IanBenzMaxim | 0:33d4e66780c0 | 295 | list<string>::iterator nextLineIt = lineIt; |
IanBenzMaxim | 0:33d4e66780c0 | 296 | nextLineIt++; |
IanBenzMaxim | 0:33d4e66780c0 | 297 | |
IanBenzMaxim | 0:33d4e66780c0 | 298 | // Wrap current line. |
IanBenzMaxim | 0:33d4e66780c0 | 299 | list<string> wrappedLines = wrapLines(*lineIt, lineLen); |
IanBenzMaxim | 0:33d4e66780c0 | 300 | m_textLines.splice(lineIt, wrappedLines); |
IanBenzMaxim | 0:33d4e66780c0 | 301 | // Remove old line. |
IanBenzMaxim | 0:33d4e66780c0 | 302 | m_textLines.erase(lineIt); |
IanBenzMaxim | 0:33d4e66780c0 | 303 | |
IanBenzMaxim | 0:33d4e66780c0 | 304 | lineIt = nextLineIt; |
IanBenzMaxim | 0:33d4e66780c0 | 305 | } |
IanBenzMaxim | 0:33d4e66780c0 | 306 | } |
IanBenzMaxim | 0:33d4e66780c0 | 307 | |
IanBenzMaxim | 0:33d4e66780c0 | 308 | // Calculate preferred size. |
IanBenzMaxim | 0:33d4e66780c0 | 309 | string::size_type maxLineLength = |
IanBenzMaxim | 0:33d4e66780c0 | 310 | std::max_element(m_textLines.begin(), m_textLines.end(), compareStringLength)->length(); |
IanBenzMaxim | 0:33d4e66780c0 | 311 | m_preferredWidth = (maxLineLength > 0) ? |
IanBenzMaxim | 0:33d4e66780c0 | 312 | (maxLineLength * characterWidth) + ((maxLineLength - 1) * m_charSpacing) : 1; |
IanBenzMaxim | 0:33d4e66780c0 | 313 | m_preferredHeight = |
IanBenzMaxim | 0:33d4e66780c0 | 314 | (m_textLines.size() * characterHeight) + ((m_textLines.size() - 1) * m_lineSpacing); |
IanBenzMaxim | 0:33d4e66780c0 | 315 | |
IanBenzMaxim | 0:33d4e66780c0 | 316 | // Remove clipped text. |
IanBenzMaxim | 0:33d4e66780c0 | 317 | if (m_textLines.size() > numLines) |
IanBenzMaxim | 0:33d4e66780c0 | 318 | m_textLines.resize(numLines); |
IanBenzMaxim | 0:33d4e66780c0 | 319 | std::for_each(m_textLines.begin(), m_textLines.end(), TrimString(lineLen)); |
IanBenzMaxim | 0:33d4e66780c0 | 320 | } |
IanBenzMaxim | 0:33d4e66780c0 | 321 | |
IanBenzMaxim | 0:33d4e66780c0 | 322 | Bitmap Text::render() const |
IanBenzMaxim | 0:33d4e66780c0 | 323 | { |
IanBenzMaxim | 0:33d4e66780c0 | 324 | using std::list; |
IanBenzMaxim | 0:33d4e66780c0 | 325 | |
IanBenzMaxim | 0:33d4e66780c0 | 326 | // Render each line. |
IanBenzMaxim | 0:33d4e66780c0 | 327 | Bitmap bitmap(width(), height()); |
IanBenzMaxim | 0:33d4e66780c0 | 328 | unsigned int lineNum = 0; |
IanBenzMaxim | 0:33d4e66780c0 | 329 | for (list<string>::const_iterator lineIt = m_textLines.begin(); lineIt != m_textLines.end(); lineIt++) |
IanBenzMaxim | 0:33d4e66780c0 | 330 | { |
IanBenzMaxim | 0:33d4e66780c0 | 331 | // Render each character. |
IanBenzMaxim | 0:33d4e66780c0 | 332 | for (string::size_type charNum = 0; charNum < lineIt->length(); charNum++) |
IanBenzMaxim | 0:33d4e66780c0 | 333 | { |
IanBenzMaxim | 0:33d4e66780c0 | 334 | Bitmap character(characterWidth, characterHeight, |
IanBenzMaxim | 0:33d4e66780c0 | 335 | &characterMap[(*lineIt)[charNum] - printableCharBegin][0]); |
IanBenzMaxim | 0:33d4e66780c0 | 336 | bitmap.overlay(character, charNum * (characterWidth + m_charSpacing), |
IanBenzMaxim | 0:33d4e66780c0 | 337 | lineNum * (characterHeight + m_lineSpacing)); |
IanBenzMaxim | 0:33d4e66780c0 | 338 | } |
IanBenzMaxim | 0:33d4e66780c0 | 339 | lineNum++; |
IanBenzMaxim | 0:33d4e66780c0 | 340 | } |
IanBenzMaxim | 0:33d4e66780c0 | 341 | return bitmap; |
IanBenzMaxim | 0:33d4e66780c0 | 342 | } |