20 if (colorStr.length() > 0 && colorStr[0] ==
'#') {
21 std::string hex = colorStr.substr(1);
24 if (hex.length() == 3) {
25 hex = std::string(1, hex[0]) + std::string(1, hex[0]) +
26 std::string(1, hex[1]) + std::string(1, hex[1]) +
27 std::string(1, hex[2]) + std::string(1, hex[2]);
30 if (hex.length() == 6) {
32 unsigned int r = std::stoi(hex.substr(0, 2),
nullptr, 16);
33 unsigned int g = std::stoi(hex.substr(2, 2),
nullptr, 16);
34 unsigned int b = std::stoi(hex.substr(4, 2),
nullptr, 16);
36 outColor =
PColor(r, g, b, 255);
47 outColor =
PColor(colorStr);
57 std::vector<FormatSegment> segments;
61 bool italicOn =
false;
62 bool underlineOn =
false;
64 PColor currentColor(0, 0, 0, 255);
67 int currentIndent = 0;
70 std::string currentText;
73 while (pos < input.length()) {
75 if (input[pos] ==
'<') {
77 if (!currentText.empty()) {
79 seg.
text = currentText;
80 seg.
style = (boldOn ? 1 : 0) + (italicOn ? 2 : 0) + (underlineOn ? 4 : 0);
87 segments.push_back(seg);
92 size_t tagEnd = input.find(
'>', pos);
93 if (tagEnd == std::string::npos) {
95 currentText += input[pos];
101 std::string tag = input.substr(pos + 1, tagEnd - pos - 1);
105 bool isClosing = (tag.length() > 0 && tag[0] ==
'/');
106 std::string tagName = isClosing ? tag.substr(1) : tag;
111 size_t spacePos = tagName.find(
' ');
112 size_t eqPos = tagName.find(
'=');
116 if (spacePos != std::string::npos && (eqPos == std::string::npos || spacePos < eqPos)) {
118 tagName = tagName.substr(0, spacePos);
119 }
else if (eqPos != std::string::npos) {
121 param = tagName.substr(eqPos + 1);
122 tagName = tagName.substr(0, eqPos);
125 tagName = toLower(tagName);
128 if (tagName ==
"br" || tagName ==
"br/") {
133 if (!currentText.empty()) {
135 seg.
text = currentText;
136 seg.
style = (boldOn ? 1 : 0) + (italicOn ? 2 : 0) + (underlineOn ? 4 : 0);
143 segments.push_back(seg);
150 }
else if (tagName ==
"b") {
152 }
else if (tagName ==
"i") {
153 italicOn = !isClosing;
154 }
else if (tagName ==
"u") {
155 underlineOn = !isClosing;
156 }
else if (tagName ==
"c") {
159 }
else if (!param.empty()) {
164 }
else if (tagName ==
"size") {
170 }
else if (!param.empty()) {
172 int size = std::stoi(param);
173 if (size > 0 && size < 1000) {
181 }
else if (tagName ==
"h1" || tagName ==
"h2" || tagName ==
"h3" ||
182 tagName ==
"h4" || tagName ==
"h5" || tagName ==
"h6") {
190 int level = tagName[1] -
'0';
191 if (level == 1) currentSize = 230;
192 else if (level == 2) currentSize = 200;
193 else if (level == 3) currentSize = 170;
194 else if (level == 4) currentSize = 140;
195 else if (level == 5) currentSize = 130;
196 else if (level == 6) currentSize = 115;
199 if (!param.empty()) {
200 std::string justifyParam = toLower(param);
201 if (justifyParam ==
"left") currentJustification =
JUSTIFY_LEFT;
202 else if (justifyParam ==
"center") currentJustification =
JUSTIFY_CENTER;
203 else if (justifyParam ==
"right") currentJustification =
JUSTIFY_RIGHT;
214 }
else if (tagName ==
"indent") {
218 if (!param.empty()) {
220 indentChars = std::stoi(param);
225 currentIndent = indentChars * charWidth;
226 }
else if (tagName ==
"p") {
238 if (!param.empty() && tag.find(
"align=") == std::string::npos && tag.find(
"size=") == std::string::npos) {
240 std::string justifyParam = toLower(param);
241 if (justifyParam ==
"left") currentJustification =
JUSTIFY_LEFT;
242 else if (justifyParam ==
"center") currentJustification =
JUSTIFY_CENTER;
243 else if (justifyParam ==
"right") currentJustification =
JUSTIFY_RIGHT;
247 size_t alignPos = tag.find(
"align=");
248 if (alignPos != std::string::npos) {
249 size_t alignStart = alignPos + 6;
250 size_t alignEnd = tag.find_first_of(
" >", alignStart);
251 if (alignEnd == std::string::npos) alignEnd = tag.length();
252 std::string alignValue = toLower(tag.substr(alignStart, alignEnd - alignStart));
254 if (alignValue ==
"left") currentJustification =
JUSTIFY_LEFT;
255 else if (alignValue ==
"center") currentJustification =
JUSTIFY_CENTER;
256 else if (alignValue ==
"right") currentJustification =
JUSTIFY_RIGHT;
259 size_t sizePos = tag.find(
"size=");
260 if (sizePos != std::string::npos) {
261 size_t sizeStart = sizePos + 5;
262 size_t sizeEnd = tag.find_first_of(
" >", sizeStart);
263 if (sizeEnd == std::string::npos) sizeEnd = tag.length();
264 std::string sizeValue = tag.substr(sizeStart, sizeEnd - sizeStart);
267 int size = std::stoi(sizeValue);
268 if (size > 0 && size < 1000) {
278 }
else if (tagName ==
"hr") {
284 segments.push_back(hrSeg);
287 }
else if (tagName ==
"li") {
291 if (!currentText.empty()) {
293 seg.
text = currentText;
294 seg.
style = (boldOn ? 1 : 0) + (italicOn ? 2 : 0) + (underlineOn ? 4 : 0);
301 segments.push_back(seg);
306 if (!segments.empty()) {
308 if (!lastSeg.
text.empty() && lastSeg.
text.back() !=
'\n') {
309 lastSeg.
text +=
'\n';
315 currentIndent += 2 * charWidth;
320 liSeg.
style = (boldOn ? 1 : 0) + (italicOn ? 2 : 0) + (underlineOn ? 4 : 0);
327 segments.push_back(liSeg);
330 currentIndent += 2 * charWidth;
334 currentText += (isClosing ?
"/" :
"");
335 currentText += tagName;
336 if (!param.empty()) {
338 currentText += param;
344 char ch = input[pos];
350 if (!currentText.empty()) {
352 seg.
text = currentText;
353 seg.
style = (boldOn ? 1 : 0) + (italicOn ? 2 : 0) + (underlineOn ? 4 : 0);
360 segments.push_back(seg);
373 if (!currentText.empty()) {
375 seg.
text = currentText;
376 seg.
style = (boldOn ? 1 : 0) + (italicOn ? 2 : 0) + (underlineOn ? 4 : 0);
383 segments.push_back(seg);
387 if (segments.empty()) {
399 while (pos < input.length()) {
400 if (input[pos] ==
'<') {
402 size_t tagEnd = input.find(
'>', pos);
403 if (tagEnd == std::string::npos) {
405 result += input[pos];
411 std::string tag = input.substr(pos + 1, tagEnd - pos - 1);
412 std::string tagName = tag;
415 if (tagName.length() > 0 && tagName[0] ==
'/') {
416 tagName = tagName.substr(1);
420 size_t eqPos = tagName.find(
'=');
421 if (eqPos != std::string::npos) {
422 tagName = tagName.substr(0, eqPos);
425 tagName = toLower(tagName);
428 if (tagName ==
"b" || tagName ==
"i" || tagName ==
"u" || tagName ==
"c" ||
429 tagName ==
"size" || tagName ==
"br" || tagName ==
"br/" ||
430 tagName ==
"h1" || tagName ==
"h2" || tagName ==
"h3" ||
431 tagName ==
"h4" || tagName ==
"h5" || tagName ==
"h6" ||
432 tagName ==
"indent" || tagName ==
"hr" || tagName ==
"li" || tagName ==
"p") {
435 if (tagName ==
"br" || tagName ==
"br/") {
439 else if (tagName ==
"li") {
443 else if (tagName ==
"hr") {
444 result +=
"--------------------\n";
449 result += input[pos];
454 result += input[pos];