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@11:989eabe2a376, 2017-05-03 (annotated)
- Committer:
- IanBenzMaxim
- Date:
- Wed May 03 16:08:59 2017 -0500
- Revision:
- 11:989eabe2a376
- Parent:
- 10:71359af61af8
- Child:
- 13:6a6225690c2e
Changed to always using scanline encoding for bitmaps.
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 | 8:a0d75dff3c9b | 42 | static const int invalidWidthHeight = -1; |
| IanBenzMaxim | 8:a0d75dff3c9b | 43 | |
| IanBenzMaxim | 8:a0d75dff3c9b | 44 | static const int characterWidth = 5; |
| IanBenzMaxim | 8:a0d75dff3c9b | 45 | static const int characterHeight = 7; |
| IanBenzMaxim | 0:33d4e66780c0 | 46 | |
| IanBenzMaxim | 0:33d4e66780c0 | 47 | static const unsigned char printableCharBegin = 0x20; |
| IanBenzMaxim | 0:33d4e66780c0 | 48 | static const unsigned char printableCharEnd = 0x7E; |
| IanBenzMaxim | 0:33d4e66780c0 | 49 | |
| IanBenzMaxim | 11:989eabe2a376 | 50 | static const uint8_t characterMap[][characterHeight] = { |
| IanBenzMaxim | 11:989eabe2a376 | 51 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // ' ' |
| IanBenzMaxim | 11:989eabe2a376 | 52 | { 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x20 }, // '!' |
| IanBenzMaxim | 11:989eabe2a376 | 53 | { 0x50, 0x50, 0x50, 0x00, 0x00, 0x00, 0x00 }, // '"' |
| IanBenzMaxim | 11:989eabe2a376 | 54 | { 0x50, 0x50, 0xF8, 0x50, 0xF8, 0x50, 0x50 }, // '#' |
| IanBenzMaxim | 11:989eabe2a376 | 55 | { 0x20, 0x78, 0xA0, 0x70, 0x28, 0xF0, 0x20 }, // '$' |
| IanBenzMaxim | 11:989eabe2a376 | 56 | { 0xC0, 0xC8, 0x10, 0x20, 0x40, 0x98, 0x18 }, // '%' |
| IanBenzMaxim | 11:989eabe2a376 | 57 | { 0x60, 0x90, 0xA0, 0x40, 0xA8, 0x90, 0x68 }, // '&' |
| IanBenzMaxim | 11:989eabe2a376 | 58 | { 0x60, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00 }, // ''' |
| IanBenzMaxim | 11:989eabe2a376 | 59 | { 0x10, 0x20, 0x40, 0x40, 0x40, 0x20, 0x10 }, // '(' |
| IanBenzMaxim | 11:989eabe2a376 | 60 | { 0x40, 0x20, 0x10, 0x10, 0x10, 0x20, 0x40 }, // ')' |
| IanBenzMaxim | 11:989eabe2a376 | 61 | { 0x00, 0x20, 0xA8, 0x70, 0xA8, 0x20, 0x00 }, // '*' |
| IanBenzMaxim | 11:989eabe2a376 | 62 | { 0x00, 0x20, 0x20, 0xF8, 0x20, 0x20, 0x00 }, // '+' |
| IanBenzMaxim | 11:989eabe2a376 | 63 | { 0x00, 0x00, 0x00, 0x00, 0x60, 0x20, 0x40 }, // ',' |
| IanBenzMaxim | 11:989eabe2a376 | 64 | { 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00 }, // '-' |
| IanBenzMaxim | 11:989eabe2a376 | 65 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60 }, // '.' |
| IanBenzMaxim | 11:989eabe2a376 | 66 | { 0x00, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00 }, // '/' |
| IanBenzMaxim | 11:989eabe2a376 | 67 | { 0x70, 0x88, 0x98, 0xA8, 0xC8, 0x88, 0x70 }, // '0' |
| IanBenzMaxim | 11:989eabe2a376 | 68 | { 0x20, 0x60, 0x20, 0x20, 0x20, 0x20, 0x70 }, // '1' |
| IanBenzMaxim | 11:989eabe2a376 | 69 | { 0x70, 0x88, 0x08, 0x10, 0x20, 0x40, 0xF8 }, // '2' |
| IanBenzMaxim | 11:989eabe2a376 | 70 | { 0xF8, 0x10, 0x20, 0x10, 0x08, 0x88, 0x70 }, // '3' |
| IanBenzMaxim | 11:989eabe2a376 | 71 | { 0x10, 0x30, 0x50, 0x90, 0xF8, 0x10, 0x10 }, // '4' |
| IanBenzMaxim | 11:989eabe2a376 | 72 | { 0xF8, 0x80, 0xF0, 0x08, 0x08, 0x88, 0x70 }, // '5' |
| IanBenzMaxim | 11:989eabe2a376 | 73 | { 0x30, 0x40, 0x80, 0xF0, 0x88, 0x88, 0x70 }, // '6' |
| IanBenzMaxim | 11:989eabe2a376 | 74 | { 0xF8, 0x08, 0x10, 0x20, 0x40, 0x40, 0x40 }, // '7' |
| IanBenzMaxim | 11:989eabe2a376 | 75 | { 0x70, 0x88, 0x88, 0x70, 0x88, 0x88, 0x70 }, // '8' |
| IanBenzMaxim | 11:989eabe2a376 | 76 | { 0x70, 0x88, 0x88, 0x78, 0x08, 0x10, 0x60 }, // '9' |
| IanBenzMaxim | 11:989eabe2a376 | 77 | { 0x00, 0x60, 0x60, 0x00, 0x60, 0x60, 0x00 }, // ':' |
| IanBenzMaxim | 11:989eabe2a376 | 78 | { 0x00, 0x60, 0x60, 0x00, 0x60, 0x20, 0x40 }, // ';' |
| IanBenzMaxim | 11:989eabe2a376 | 79 | { 0x10, 0x20, 0x40, 0x80, 0x40, 0x20, 0x10 }, // '<' |
| IanBenzMaxim | 11:989eabe2a376 | 80 | { 0x00, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0x00 }, // '=' |
| IanBenzMaxim | 11:989eabe2a376 | 81 | { 0x40, 0x20, 0x10, 0x08, 0x10, 0x20, 0x40 }, // '>' |
| IanBenzMaxim | 11:989eabe2a376 | 82 | { 0x70, 0x88, 0x08, 0x10, 0x20, 0x00, 0x20 }, // '?' |
| IanBenzMaxim | 11:989eabe2a376 | 83 | { 0x70, 0x88, 0x08, 0x68, 0xA8, 0xA8, 0x70 }, // '@' |
| IanBenzMaxim | 11:989eabe2a376 | 84 | { 0x70, 0x88, 0x88, 0x88, 0xF8, 0x88, 0x88 }, // 'A' |
| IanBenzMaxim | 11:989eabe2a376 | 85 | { 0xF0, 0x88, 0x88, 0xF0, 0x88, 0x88, 0xF0 }, // 'B' |
| IanBenzMaxim | 11:989eabe2a376 | 86 | { 0x70, 0x88, 0x80, 0x80, 0x80, 0x88, 0x70 }, // 'C' |
| IanBenzMaxim | 11:989eabe2a376 | 87 | { 0xE0, 0x90, 0x88, 0x88, 0x88, 0x90, 0xE0 }, // 'D' |
| IanBenzMaxim | 11:989eabe2a376 | 88 | { 0xF8, 0x80, 0x80, 0xF0, 0x80, 0x80, 0xF8 }, // 'E' |
| IanBenzMaxim | 11:989eabe2a376 | 89 | { 0xF8, 0x80, 0x80, 0xF0, 0x80, 0x80, 0x80 }, // 'F' |
| IanBenzMaxim | 11:989eabe2a376 | 90 | { 0x70, 0x88, 0x80, 0xB8, 0x88, 0x88, 0x78 }, // 'G' |
| IanBenzMaxim | 11:989eabe2a376 | 91 | { 0x88, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x88 }, // 'H' |
| IanBenzMaxim | 11:989eabe2a376 | 92 | { 0x70, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70 }, // 'I' |
| IanBenzMaxim | 11:989eabe2a376 | 93 | { 0x38, 0x10, 0x10, 0x10, 0x10, 0x90, 0x60 }, // 'J' |
| IanBenzMaxim | 11:989eabe2a376 | 94 | { 0x88, 0x90, 0xA0, 0xC0, 0xA0, 0x90, 0x88 }, // 'K' |
| IanBenzMaxim | 11:989eabe2a376 | 95 | { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xF8 }, // 'L' |
| IanBenzMaxim | 11:989eabe2a376 | 96 | { 0x88, 0xD8, 0xA8, 0xA8, 0x88, 0x88, 0x88 }, // 'M' |
| IanBenzMaxim | 11:989eabe2a376 | 97 | { 0x88, 0x88, 0xC8, 0xA8, 0x98, 0x88, 0x88 }, // 'N' |
| IanBenzMaxim | 11:989eabe2a376 | 98 | { 0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70 }, // 'O' |
| IanBenzMaxim | 11:989eabe2a376 | 99 | { 0xF0, 0x88, 0x88, 0xF0, 0x80, 0x80, 0x80 }, // 'P' |
| IanBenzMaxim | 11:989eabe2a376 | 100 | { 0x70, 0x88, 0x88, 0x88, 0xA8, 0x90, 0x68 }, // 'Q' |
| IanBenzMaxim | 11:989eabe2a376 | 101 | { 0xF0, 0x88, 0x88, 0xF0, 0xA0, 0x90, 0x88 }, // 'R' |
| IanBenzMaxim | 11:989eabe2a376 | 102 | { 0x78, 0x80, 0x80, 0x70, 0x08, 0x08, 0xF0 }, // 'S' |
| IanBenzMaxim | 11:989eabe2a376 | 103 | { 0xF8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }, // 'T' |
| IanBenzMaxim | 11:989eabe2a376 | 104 | { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70 }, // 'U' |
| IanBenzMaxim | 11:989eabe2a376 | 105 | { 0x88, 0x88, 0x88, 0x88, 0x88, 0x50, 0x20 }, // 'V' |
| IanBenzMaxim | 11:989eabe2a376 | 106 | { 0x88, 0x88, 0x88, 0xA8, 0xA8, 0xA8, 0x50 }, // 'W' |
| IanBenzMaxim | 11:989eabe2a376 | 107 | { 0x88, 0x88, 0x50, 0x20, 0x50, 0x88, 0x88 }, // 'X' |
| IanBenzMaxim | 11:989eabe2a376 | 108 | { 0x88, 0x88, 0x88, 0x50, 0x20, 0x20, 0x20 }, // 'Y' |
| IanBenzMaxim | 11:989eabe2a376 | 109 | { 0xF8, 0x08, 0x10, 0x20, 0x40, 0x80, 0xF8 }, // 'Z' |
| IanBenzMaxim | 11:989eabe2a376 | 110 | { 0x70, 0x40, 0x40, 0x40, 0x40, 0x40, 0x70 }, // '[' |
| IanBenzMaxim | 11:989eabe2a376 | 111 | { 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x00 }, // '\' |
| IanBenzMaxim | 11:989eabe2a376 | 112 | { 0x70, 0x10, 0x10, 0x10, 0x10, 0x10, 0x70 }, // ']' |
| IanBenzMaxim | 11:989eabe2a376 | 113 | { 0x20, 0x50, 0x88, 0x00, 0x00, 0x00, 0x00 }, // '^' |
| IanBenzMaxim | 11:989eabe2a376 | 114 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8 }, // '_' |
| IanBenzMaxim | 11:989eabe2a376 | 115 | { 0x40, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00 }, // '`' |
| IanBenzMaxim | 11:989eabe2a376 | 116 | { 0x00, 0x00, 0x70, 0x08, 0x78, 0x88, 0x78 }, // 'a' |
| IanBenzMaxim | 11:989eabe2a376 | 117 | { 0x80, 0x80, 0xB0, 0xC8, 0x88, 0x88, 0xF0 }, // 'b' |
| IanBenzMaxim | 11:989eabe2a376 | 118 | { 0x00, 0x00, 0x70, 0x80, 0x80, 0x88, 0x70 }, // 'c' |
| IanBenzMaxim | 11:989eabe2a376 | 119 | { 0x08, 0x08, 0x68, 0x98, 0x88, 0x88, 0x78 }, // 'd' |
| IanBenzMaxim | 11:989eabe2a376 | 120 | { 0x00, 0x00, 0x70, 0x88, 0xF8, 0x80, 0x70 }, // 'e' |
| IanBenzMaxim | 11:989eabe2a376 | 121 | { 0x30, 0x48, 0x40, 0xE0, 0x40, 0x40, 0x40 }, // 'f' |
| IanBenzMaxim | 11:989eabe2a376 | 122 | { 0x00, 0x78, 0x88, 0x88, 0x78, 0x08, 0x70 }, // 'g' |
| IanBenzMaxim | 11:989eabe2a376 | 123 | { 0x80, 0x80, 0xB0, 0xC8, 0x88, 0x88, 0x88 }, // 'h' |
| IanBenzMaxim | 11:989eabe2a376 | 124 | { 0x20, 0x00, 0x60, 0x20, 0x20, 0x20, 0x70 }, // 'i' |
| IanBenzMaxim | 11:989eabe2a376 | 125 | { 0x10, 0x00, 0x30, 0x10, 0x10, 0x90, 0x60 }, // 'j' |
| IanBenzMaxim | 11:989eabe2a376 | 126 | { 0x80, 0x80, 0x90, 0xA0, 0xC0, 0xA0, 0x90 }, // 'k' |
| IanBenzMaxim | 11:989eabe2a376 | 127 | { 0x60, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70 }, // 'l' |
| IanBenzMaxim | 11:989eabe2a376 | 128 | { 0x00, 0x00, 0xD0, 0xA8, 0xA8, 0x88, 0x88 }, // 'm' |
| IanBenzMaxim | 11:989eabe2a376 | 129 | { 0x00, 0x00, 0xB0, 0xC8, 0x88, 0x88, 0x88 }, // 'n' |
| IanBenzMaxim | 11:989eabe2a376 | 130 | { 0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x70 }, // 'o' |
| IanBenzMaxim | 11:989eabe2a376 | 131 | { 0x00, 0x00, 0xF0, 0x88, 0xF0, 0x80, 0x80 }, // 'p' |
| IanBenzMaxim | 11:989eabe2a376 | 132 | { 0x00, 0x00, 0x68, 0x98, 0x78, 0x08, 0x08 }, // 'q' |
| IanBenzMaxim | 11:989eabe2a376 | 133 | { 0x00, 0x00, 0xB0, 0xC8, 0x80, 0x80, 0x80 }, // 'r' |
| IanBenzMaxim | 11:989eabe2a376 | 134 | { 0x00, 0x00, 0x70, 0x80, 0x70, 0x08, 0xF0 }, // 's' |
| IanBenzMaxim | 11:989eabe2a376 | 135 | { 0x40, 0x40, 0xE0, 0x40, 0x40, 0x48, 0x30 }, // 't' |
| IanBenzMaxim | 11:989eabe2a376 | 136 | { 0x00, 0x00, 0x88, 0x88, 0x88, 0x98, 0x68 }, // 'u' |
| IanBenzMaxim | 11:989eabe2a376 | 137 | { 0x00, 0x00, 0x88, 0x88, 0x88, 0x41, 0x20 }, // 'v' |
| IanBenzMaxim | 11:989eabe2a376 | 138 | { 0x00, 0x00, 0x88, 0x88, 0xA8, 0xA8, 0x50 }, // 'w' |
| IanBenzMaxim | 11:989eabe2a376 | 139 | { 0x00, 0x00, 0x88, 0x50, 0x20, 0x50, 0x88 }, // 'x' |
| IanBenzMaxim | 11:989eabe2a376 | 140 | { 0x00, 0x00, 0x88, 0x88, 0x78, 0x08, 0x70 }, // 'y' |
| IanBenzMaxim | 11:989eabe2a376 | 141 | { 0x00, 0x00, 0xF8, 0x10, 0x20, 0x40, 0xF8 }, // 'z' |
| IanBenzMaxim | 11:989eabe2a376 | 142 | { 0x10, 0x20, 0x20, 0x40, 0x20, 0x20, 0x10 }, // '{' |
| IanBenzMaxim | 11:989eabe2a376 | 143 | { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }, // '|' |
| IanBenzMaxim | 11:989eabe2a376 | 144 | { 0x40, 0x20, 0x20, 0x10, 0x20, 0x20, 0x40 }, // '}' |
| IanBenzMaxim | 11:989eabe2a376 | 145 | { 0x00, 0x00, 0x40, 0xA8, 0x10, 0x00, 0x00 } // '~' |
| IanBenzMaxim | 0:33d4e66780c0 | 146 | }; |
| IanBenzMaxim | 0:33d4e66780c0 | 147 | |
| IanBenzMaxim | 0:33d4e66780c0 | 148 | static bool charPrintable(unsigned char c) |
| IanBenzMaxim | 0:33d4e66780c0 | 149 | { |
| IanBenzMaxim | 0:33d4e66780c0 | 150 | return (c >= printableCharBegin) && (c <= printableCharEnd); |
| IanBenzMaxim | 0:33d4e66780c0 | 151 | } |
| IanBenzMaxim | 0:33d4e66780c0 | 152 | |
| IanBenzMaxim | 0:33d4e66780c0 | 153 | static void removeNonprintableChars(string & s) |
| IanBenzMaxim | 0:33d4e66780c0 | 154 | { |
| IanBenzMaxim | 3:d2799d8497c0 | 155 | s.erase(std::remove_if(s.begin(), s.end(), std::not1(std::ptr_fun(charPrintable))), s.end()); |
| IanBenzMaxim | 0:33d4e66780c0 | 156 | } |
| IanBenzMaxim | 0:33d4e66780c0 | 157 | |
| IanBenzMaxim | 0:33d4e66780c0 | 158 | static bool compareStringLength(const string & a, const string & b) |
| IanBenzMaxim | 0:33d4e66780c0 | 159 | { |
| IanBenzMaxim | 0:33d4e66780c0 | 160 | return a.length() < b.length(); |
| IanBenzMaxim | 0:33d4e66780c0 | 161 | } |
| IanBenzMaxim | 0:33d4e66780c0 | 162 | |
| IanBenzMaxim | 0:33d4e66780c0 | 163 | // Functor trims string if it exceeds a certain length. |
| IanBenzMaxim | 0:33d4e66780c0 | 164 | class TrimString |
| IanBenzMaxim | 0:33d4e66780c0 | 165 | { |
| IanBenzMaxim | 0:33d4e66780c0 | 166 | public: |
| IanBenzMaxim | 0:33d4e66780c0 | 167 | TrimString(string::size_type maxSize) : maxSize(maxSize) { } |
| IanBenzMaxim | 0:33d4e66780c0 | 168 | |
| IanBenzMaxim | 0:33d4e66780c0 | 169 | void operator()(string & s) |
| IanBenzMaxim | 0:33d4e66780c0 | 170 | { |
| IanBenzMaxim | 0:33d4e66780c0 | 171 | if (s.size() > maxSize) |
| IanBenzMaxim | 0:33d4e66780c0 | 172 | { |
| IanBenzMaxim | 0:33d4e66780c0 | 173 | s.resize(maxSize); |
| IanBenzMaxim | 0:33d4e66780c0 | 174 | } |
| IanBenzMaxim | 0:33d4e66780c0 | 175 | } |
| IanBenzMaxim | 0:33d4e66780c0 | 176 | |
| IanBenzMaxim | 0:33d4e66780c0 | 177 | private: |
| IanBenzMaxim | 0:33d4e66780c0 | 178 | string::size_type maxSize; |
| IanBenzMaxim | 0:33d4e66780c0 | 179 | }; |
| IanBenzMaxim | 0:33d4e66780c0 | 180 | |
| IanBenzMaxim | 0:33d4e66780c0 | 181 | // Split a string based on a character token. Token will be removed. |
| IanBenzMaxim | 0:33d4e66780c0 | 182 | static std::list<string> tokenizeString(const string & toSplit, char token) |
| IanBenzMaxim | 0:33d4e66780c0 | 183 | { |
| IanBenzMaxim | 0:33d4e66780c0 | 184 | std::list<string> toSplitLines; |
| IanBenzMaxim | 0:33d4e66780c0 | 185 | string::size_type beginIdx = 0, endIdx; |
| IanBenzMaxim | 0:33d4e66780c0 | 186 | do |
| IanBenzMaxim | 0:33d4e66780c0 | 187 | { |
| IanBenzMaxim | 0:33d4e66780c0 | 188 | endIdx = toSplit.find(token, beginIdx); |
| IanBenzMaxim | 0:33d4e66780c0 | 189 | toSplitLines.push_back(toSplit.substr(beginIdx, endIdx == string::npos ? string::npos : endIdx - beginIdx)); |
| IanBenzMaxim | 0:33d4e66780c0 | 190 | beginIdx = endIdx + 1; |
| IanBenzMaxim | 0:33d4e66780c0 | 191 | } while (endIdx != string::npos); |
| IanBenzMaxim | 0:33d4e66780c0 | 192 | return toSplitLines; |
| IanBenzMaxim | 0:33d4e66780c0 | 193 | } |
| IanBenzMaxim | 0:33d4e66780c0 | 194 | |
| IanBenzMaxim | 0:33d4e66780c0 | 195 | // Word wrap string into lines based on a specified line length. |
| IanBenzMaxim | 0:33d4e66780c0 | 196 | static std::list<string> wrapLines(const string & toSplit, const string::size_type lineLen) |
| IanBenzMaxim | 0:33d4e66780c0 | 197 | { |
| IanBenzMaxim | 0:33d4e66780c0 | 198 | std::list<string> toSplitLines; |
| IanBenzMaxim | 0:33d4e66780c0 | 199 | string::size_type beginIdx = 0; |
| IanBenzMaxim | 0:33d4e66780c0 | 200 | if (lineLen > 0) |
| IanBenzMaxim | 0:33d4e66780c0 | 201 | { |
| IanBenzMaxim | 0:33d4e66780c0 | 202 | // Split lines as much as necessary. |
| IanBenzMaxim | 0:33d4e66780c0 | 203 | string::size_type endIdx = lineLen; |
| IanBenzMaxim | 0:33d4e66780c0 | 204 | while (((toSplit.length() - beginIdx) > lineLen) && (endIdx != string::npos)) |
| IanBenzMaxim | 0:33d4e66780c0 | 205 | { |
| IanBenzMaxim | 0:33d4e66780c0 | 206 | endIdx = toSplit.rfind(' ', endIdx); |
| IanBenzMaxim | 0:33d4e66780c0 | 207 | if ((endIdx == string::npos) || (endIdx <= beginIdx)) |
| IanBenzMaxim | 0:33d4e66780c0 | 208 | { |
| IanBenzMaxim | 0:33d4e66780c0 | 209 | // Current word is too long to split. Find end of current word. |
| IanBenzMaxim | 0:33d4e66780c0 | 210 | endIdx = toSplit.find(' ', beginIdx); |
| IanBenzMaxim | 0:33d4e66780c0 | 211 | } |
| IanBenzMaxim | 0:33d4e66780c0 | 212 | if (endIdx != string::npos) |
| IanBenzMaxim | 0:33d4e66780c0 | 213 | { |
| IanBenzMaxim | 0:33d4e66780c0 | 214 | toSplitLines.push_back(toSplit.substr(beginIdx, endIdx - beginIdx)); |
| IanBenzMaxim | 0:33d4e66780c0 | 215 | beginIdx = endIdx + 1; |
| IanBenzMaxim | 0:33d4e66780c0 | 216 | endIdx = beginIdx + lineLen; |
| IanBenzMaxim | 0:33d4e66780c0 | 217 | } |
| IanBenzMaxim | 0:33d4e66780c0 | 218 | } |
| IanBenzMaxim | 0:33d4e66780c0 | 219 | } |
| IanBenzMaxim | 0:33d4e66780c0 | 220 | // Last line is any remaining characters. |
| IanBenzMaxim | 0:33d4e66780c0 | 221 | toSplitLines.push_back(toSplit.substr(beginIdx, toSplit.length() - beginIdx)); |
| IanBenzMaxim | 0:33d4e66780c0 | 222 | return toSplitLines; |
| IanBenzMaxim | 0:33d4e66780c0 | 223 | } |
| IanBenzMaxim | 0:33d4e66780c0 | 224 | |
| IanBenzMaxim | 8:a0d75dff3c9b | 225 | Text::Text() : m_text(), m_wordWrap(false), m_charSpacing(1), m_lineSpacing(1), |
| IanBenzMaxim | 8:a0d75dff3c9b | 226 | m_textLines(), m_preferredWidth(invalidWidthHeight), m_preferredHeight(invalidWidthHeight) { } |
| IanBenzMaxim | 0:33d4e66780c0 | 227 | |
| IanBenzMaxim | 6:0c9050b02876 | 228 | void Text::setText(const string & text) |
| IanBenzMaxim | 0:33d4e66780c0 | 229 | { |
| IanBenzMaxim | 0:33d4e66780c0 | 230 | if (m_text != text) |
| IanBenzMaxim | 0:33d4e66780c0 | 231 | { |
| IanBenzMaxim | 0:33d4e66780c0 | 232 | m_text = text; |
| IanBenzMaxim | 8:a0d75dff3c9b | 233 | invalidate(); |
| IanBenzMaxim | 8:a0d75dff3c9b | 234 | m_preferredWidth = m_preferredHeight = invalidWidthHeight; |
| IanBenzMaxim | 0:33d4e66780c0 | 235 | } |
| IanBenzMaxim | 0:33d4e66780c0 | 236 | } |
| IanBenzMaxim | 0:33d4e66780c0 | 237 | |
| IanBenzMaxim | 0:33d4e66780c0 | 238 | void Text::setWordWrap(bool wordWrap) |
| IanBenzMaxim | 0:33d4e66780c0 | 239 | { |
| IanBenzMaxim | 0:33d4e66780c0 | 240 | if (m_wordWrap != wordWrap) |
| IanBenzMaxim | 0:33d4e66780c0 | 241 | { |
| IanBenzMaxim | 0:33d4e66780c0 | 242 | m_wordWrap = wordWrap; |
| IanBenzMaxim | 8:a0d75dff3c9b | 243 | invalidate(); |
| IanBenzMaxim | 8:a0d75dff3c9b | 244 | m_preferredWidth = m_preferredHeight = invalidWidthHeight; |
| IanBenzMaxim | 0:33d4e66780c0 | 245 | } |
| IanBenzMaxim | 0:33d4e66780c0 | 246 | } |
| IanBenzMaxim | 0:33d4e66780c0 | 247 | |
| IanBenzMaxim | 8:a0d75dff3c9b | 248 | void Text::setLineSpacing(int lineSpacing) |
| IanBenzMaxim | 0:33d4e66780c0 | 249 | { |
| IanBenzMaxim | 8:a0d75dff3c9b | 250 | if (lineSpacing > 0 && m_lineSpacing != lineSpacing) |
| IanBenzMaxim | 0:33d4e66780c0 | 251 | { |
| IanBenzMaxim | 0:33d4e66780c0 | 252 | m_lineSpacing = lineSpacing; |
| IanBenzMaxim | 8:a0d75dff3c9b | 253 | invalidate(); |
| IanBenzMaxim | 8:a0d75dff3c9b | 254 | m_preferredHeight = invalidWidthHeight; |
| IanBenzMaxim | 8:a0d75dff3c9b | 255 | } |
| IanBenzMaxim | 8:a0d75dff3c9b | 256 | } |
| IanBenzMaxim | 8:a0d75dff3c9b | 257 | |
| IanBenzMaxim | 8:a0d75dff3c9b | 258 | void Text::setCharSpacing(int charSpacing) |
| IanBenzMaxim | 8:a0d75dff3c9b | 259 | { |
| IanBenzMaxim | 8:a0d75dff3c9b | 260 | if (charSpacing > 0 && m_charSpacing != charSpacing) |
| IanBenzMaxim | 8:a0d75dff3c9b | 261 | { |
| IanBenzMaxim | 8:a0d75dff3c9b | 262 | m_charSpacing = charSpacing; |
| IanBenzMaxim | 8:a0d75dff3c9b | 263 | invalidate(); |
| IanBenzMaxim | 8:a0d75dff3c9b | 264 | m_preferredWidth = invalidWidthHeight; |
| IanBenzMaxim | 8:a0d75dff3c9b | 265 | if (wordWrap()) |
| IanBenzMaxim | 8:a0d75dff3c9b | 266 | { |
| IanBenzMaxim | 8:a0d75dff3c9b | 267 | m_preferredHeight = invalidWidthHeight; |
| IanBenzMaxim | 8:a0d75dff3c9b | 268 | } |
| IanBenzMaxim | 0:33d4e66780c0 | 269 | } |
| IanBenzMaxim | 0:33d4e66780c0 | 270 | } |
| IanBenzMaxim | 0:33d4e66780c0 | 271 | |
| IanBenzMaxim | 8:a0d75dff3c9b | 272 | int Text::preferredWidth() const |
| IanBenzMaxim | 8:a0d75dff3c9b | 273 | { |
| IanBenzMaxim | 8:a0d75dff3c9b | 274 | if (m_preferredWidth == invalidWidthHeight) |
| IanBenzMaxim | 8:a0d75dff3c9b | 275 | { |
| IanBenzMaxim | 8:a0d75dff3c9b | 276 | calculateLayout(); |
| IanBenzMaxim | 8:a0d75dff3c9b | 277 | } |
| IanBenzMaxim | 8:a0d75dff3c9b | 278 | return m_preferredWidth; |
| IanBenzMaxim | 8:a0d75dff3c9b | 279 | } |
| IanBenzMaxim | 8:a0d75dff3c9b | 280 | |
| IanBenzMaxim | 8:a0d75dff3c9b | 281 | int Text::preferredHeight() const |
| IanBenzMaxim | 0:33d4e66780c0 | 282 | { |
| IanBenzMaxim | 8:a0d75dff3c9b | 283 | if (m_preferredHeight == invalidWidthHeight) |
| IanBenzMaxim | 0:33d4e66780c0 | 284 | { |
| IanBenzMaxim | 8:a0d75dff3c9b | 285 | calculateLayout(); |
| IanBenzMaxim | 8:a0d75dff3c9b | 286 | } |
| IanBenzMaxim | 8:a0d75dff3c9b | 287 | return m_preferredHeight; |
| IanBenzMaxim | 8:a0d75dff3c9b | 288 | } |
| IanBenzMaxim | 8:a0d75dff3c9b | 289 | |
| IanBenzMaxim | 8:a0d75dff3c9b | 290 | void Text::resized() |
| IanBenzMaxim | 8:a0d75dff3c9b | 291 | { |
| IanBenzMaxim | 8:a0d75dff3c9b | 292 | m_preferredWidth = invalidWidthHeight; |
| IanBenzMaxim | 8:a0d75dff3c9b | 293 | if (wordWrap()) |
| IanBenzMaxim | 8:a0d75dff3c9b | 294 | { |
| IanBenzMaxim | 8:a0d75dff3c9b | 295 | m_preferredHeight = invalidWidthHeight; |
| IanBenzMaxim | 0:33d4e66780c0 | 296 | } |
| IanBenzMaxim | 0:33d4e66780c0 | 297 | } |
| IanBenzMaxim | 8:a0d75dff3c9b | 298 | |
| IanBenzMaxim | 10:71359af61af8 | 299 | void Text::doRender(Bitmap & bitmap, int xOffset, int yOffset) const |
| IanBenzMaxim | 8:a0d75dff3c9b | 300 | { |
| IanBenzMaxim | 8:a0d75dff3c9b | 301 | using std::list; |
| IanBenzMaxim | 0:33d4e66780c0 | 302 | |
| IanBenzMaxim | 8:a0d75dff3c9b | 303 | // Ensure layout is up to date. |
| IanBenzMaxim | 8:a0d75dff3c9b | 304 | if (m_preferredWidth == invalidWidthHeight || m_preferredHeight == invalidWidthHeight) |
| IanBenzMaxim | 8:a0d75dff3c9b | 305 | { |
| IanBenzMaxim | 8:a0d75dff3c9b | 306 | calculateLayout(); |
| IanBenzMaxim | 8:a0d75dff3c9b | 307 | } |
| IanBenzMaxim | 8:a0d75dff3c9b | 308 | |
| IanBenzMaxim | 8:a0d75dff3c9b | 309 | // Render each line. |
| IanBenzMaxim | 8:a0d75dff3c9b | 310 | int lineNum = 0; |
| IanBenzMaxim | 8:a0d75dff3c9b | 311 | for (list<string>::const_iterator lineIt = m_textLines.begin(); lineIt != m_textLines.end(); lineIt++) |
| IanBenzMaxim | 8:a0d75dff3c9b | 312 | { |
| IanBenzMaxim | 8:a0d75dff3c9b | 313 | // Render each character. |
| IanBenzMaxim | 8:a0d75dff3c9b | 314 | for (string::size_type charNum = 0; charNum < lineIt->length(); charNum++) |
| IanBenzMaxim | 8:a0d75dff3c9b | 315 | { |
| IanBenzMaxim | 10:71359af61af8 | 316 | bitmap.overlay( |
| IanBenzMaxim | 10:71359af61af8 | 317 | xOffset + x() + charNum * (characterWidth + m_charSpacing), |
| IanBenzMaxim | 11:989eabe2a376 | 318 | yOffset + y() + lineNum * (characterHeight + m_lineSpacing), |
| IanBenzMaxim | 11:989eabe2a376 | 319 | &characterMap[(*lineIt)[charNum] - printableCharBegin][0], |
| IanBenzMaxim | 11:989eabe2a376 | 320 | characterHeight, |
| IanBenzMaxim | 11:989eabe2a376 | 321 | characterWidth |
| IanBenzMaxim | 10:71359af61af8 | 322 | ); |
| IanBenzMaxim | 8:a0d75dff3c9b | 323 | } |
| IanBenzMaxim | 8:a0d75dff3c9b | 324 | lineNum++; |
| IanBenzMaxim | 8:a0d75dff3c9b | 325 | } |
| IanBenzMaxim | 8:a0d75dff3c9b | 326 | } |
| IanBenzMaxim | 8:a0d75dff3c9b | 327 | |
| IanBenzMaxim | 8:a0d75dff3c9b | 328 | void Text::calculateLayout() const |
| IanBenzMaxim | 0:33d4e66780c0 | 329 | { |
| IanBenzMaxim | 0:33d4e66780c0 | 330 | using std::list; |
| IanBenzMaxim | 0:33d4e66780c0 | 331 | |
| IanBenzMaxim | 0:33d4e66780c0 | 332 | // Split string into lines. |
| IanBenzMaxim | 0:33d4e66780c0 | 333 | m_textLines = tokenizeString(m_text, '\n'); |
| IanBenzMaxim | 0:33d4e66780c0 | 334 | |
| IanBenzMaxim | 0:33d4e66780c0 | 335 | // Remove non-printable characters. |
| IanBenzMaxim | 0:33d4e66780c0 | 336 | std::for_each(m_textLines.begin(), m_textLines.end(), removeNonprintableChars); |
| IanBenzMaxim | 0:33d4e66780c0 | 337 | |
| IanBenzMaxim | 8:a0d75dff3c9b | 338 | const int lineLen = |
| IanBenzMaxim | 0:33d4e66780c0 | 339 | (width() / (characterWidth + m_charSpacing)) + |
| IanBenzMaxim | 0:33d4e66780c0 | 340 | (((width() % (characterWidth + m_charSpacing)) >= characterWidth) ? 1 : 0); |
| IanBenzMaxim | 8:a0d75dff3c9b | 341 | const int numLines = |
| IanBenzMaxim | 0:33d4e66780c0 | 342 | (height() / (characterHeight + m_lineSpacing)) + |
| IanBenzMaxim | 0:33d4e66780c0 | 343 | (((height() % (characterHeight + m_lineSpacing)) >= characterHeight) ? 1 : 0); |
| IanBenzMaxim | 0:33d4e66780c0 | 344 | |
| IanBenzMaxim | 0:33d4e66780c0 | 345 | // Word wrap lines if enabled. |
| IanBenzMaxim | 0:33d4e66780c0 | 346 | if (m_wordWrap) |
| IanBenzMaxim | 0:33d4e66780c0 | 347 | { |
| IanBenzMaxim | 0:33d4e66780c0 | 348 | list<string>::iterator lineIt = m_textLines.begin(); |
| IanBenzMaxim | 0:33d4e66780c0 | 349 | while (lineIt != m_textLines.end()) |
| IanBenzMaxim | 0:33d4e66780c0 | 350 | { |
| IanBenzMaxim | 0:33d4e66780c0 | 351 | list<string>::iterator nextLineIt = lineIt; |
| IanBenzMaxim | 0:33d4e66780c0 | 352 | nextLineIt++; |
| IanBenzMaxim | 0:33d4e66780c0 | 353 | |
| IanBenzMaxim | 0:33d4e66780c0 | 354 | // Wrap current line. |
| IanBenzMaxim | 0:33d4e66780c0 | 355 | list<string> wrappedLines = wrapLines(*lineIt, lineLen); |
| IanBenzMaxim | 0:33d4e66780c0 | 356 | m_textLines.splice(lineIt, wrappedLines); |
| IanBenzMaxim | 0:33d4e66780c0 | 357 | // Remove old line. |
| IanBenzMaxim | 0:33d4e66780c0 | 358 | m_textLines.erase(lineIt); |
| IanBenzMaxim | 0:33d4e66780c0 | 359 | |
| IanBenzMaxim | 0:33d4e66780c0 | 360 | lineIt = nextLineIt; |
| IanBenzMaxim | 0:33d4e66780c0 | 361 | } |
| IanBenzMaxim | 0:33d4e66780c0 | 362 | } |
| IanBenzMaxim | 0:33d4e66780c0 | 363 | |
| IanBenzMaxim | 0:33d4e66780c0 | 364 | // Calculate preferred size. |
| IanBenzMaxim | 0:33d4e66780c0 | 365 | string::size_type maxLineLength = |
| IanBenzMaxim | 0:33d4e66780c0 | 366 | std::max_element(m_textLines.begin(), m_textLines.end(), compareStringLength)->length(); |
| IanBenzMaxim | 0:33d4e66780c0 | 367 | m_preferredWidth = (maxLineLength > 0) ? |
| IanBenzMaxim | 0:33d4e66780c0 | 368 | (maxLineLength * characterWidth) + ((maxLineLength - 1) * m_charSpacing) : 1; |
| IanBenzMaxim | 0:33d4e66780c0 | 369 | m_preferredHeight = |
| IanBenzMaxim | 0:33d4e66780c0 | 370 | (m_textLines.size() * characterHeight) + ((m_textLines.size() - 1) * m_lineSpacing); |
| IanBenzMaxim | 0:33d4e66780c0 | 371 | |
| IanBenzMaxim | 0:33d4e66780c0 | 372 | // Remove clipped text. |
| IanBenzMaxim | 8:a0d75dff3c9b | 373 | if (m_textLines.size() > static_cast<list<string>::size_type>(numLines)) |
| IanBenzMaxim | 0:33d4e66780c0 | 374 | m_textLines.resize(numLines); |
| IanBenzMaxim | 0:33d4e66780c0 | 375 | std::for_each(m_textLines.begin(), m_textLines.end(), TrimString(lineLen)); |
| IanBenzMaxim | 0:33d4e66780c0 | 376 | } |