12#include <unicode/ubrk.h>
13#include <unicode/utypes.h>
14#include <unicode/ubidi.h>
59 result.reserve(sv.length());
61 result += char(tolower(ch));
71 if((byte1 & 0x80) == 0) {
73 }
else if((byte1 & 0xE0) == 0xC0) {
75 }
else if((byte1 & 0xF0) == 0xE0) {
77 }
else if((byte1 & 0xF8) == 0xF0) {
84 return ((b & 0x80) == 0) ? 1 : ((b & 0xE0) == 0xC0) ? 2
85 : ((b & 0xF0) == 0xE0) ? 3 : ((b & 0xF8) == 0xF0) ? 4
89 return (c == 0x3000 || c == 0x205F || c == 0x202F || c == 0x2029 || c == 0x2028 || c == 0x00A0
90 || c == 0x0085 || c <= 0x0020 || (0x2000 <= c && c <= 0x200A));
93 return c == 0x2029 || c == 0x2028 || c ==
uint32_t(
'\n') || c ==
uint32_t(
'\r');
97 auto cpos = file_content;
103 if(
int(file_content[0]) == 0xEF &&
int(file_content[1]) == 0xBB &&
int(file_content[2]) == 0xBF)
106 while(cpos < file_content + file_size) {
107 cpos = parsers::parse_fixed_amount_csv_values<14>(cpos, file_content + file_size,
';', [&](std::string_view
const* values) {
108 auto key =
state.add_key_utf8(values[0]);
109 auto entry =
state.add_locale_data_utf8(values[target_column]);
110 state.locale_key_to_text_sequence.insert_or_assign(key, entry);
114 while(cpos < file_content + file_size) {
115 cpos = parsers::parse_fixed_amount_csv_values<14>(cpos, file_content + file_size,
';', [&](std::string_view
const* values) {
116 auto key =
state.add_key_win1252(values[0]);
117 auto entry =
state.add_locale_data_win1252(values[target_column]);
118 state.locale_key_to_text_sequence.insert_or_assign(key, entry);
126 if(v.length() != (N - 1))
128 for(
unsigned int i = 0; i < N - 1; ++i) {
129 if(tolower(v[i]) != t[i])
135#define CT_STRING_ENUM(X) else if(is_fixed_token_ci(v, #X)) return variable_type::X;
138 if(v.length() == 1) {
145 }
else if(v.length() == 2) {
151 }
else if(v.length() == 3) {
206 }
else if(v.length() == 4) {
256 }
else if(v.length() == 5) {
304 }
else if(v.length() == 6) {
343 }
else if(v.length() == 7) {
388 }
else if(v.length() == 8) {
428 }
else if(v.length() == 9) {
452 }
else if(v.length() == 10) {
476 }
else if(v.length() == 11) {
493 }
else if(v.length() == 12) {
505 }
else if(v.length() == 13) {
525 }
else if(v.length() == 14) {
536 }
else if(v.length() == 15) {
542 }
else if(v.length() == 16) {
548 }
else if(v.length() == 17) {
551 }
else if(v.length() == 18) {
558 }
else if(v.length() == 19) {
563 }
else if(v.length() == 20) {
565 }
else if(v.length() == 21) {
568 }
else if(v.length() == 22) {
573 }
else if(v.length() == 23) {
575 }
else if(v.length() == 24) {
588 constexpr static char16_t converted[256] =
590 { u
' ', u
'\u0001', u
'\u0002', u
'\u0003', u
'\u0004', u
' ', u
' ', u
' ', u
' ', u
'\t', u
'\n', u
' ', u
' ', u
' ', u
' ', u
' ',
591 u
' ', u
' ', u
' ', u
' ', u
' ', u
' ', u
' ', u
' ', u
' ', u
' ', u
' ', u
' ', u
' ', u
' ', u
' ', u
' ',
592 u
' ', u
'!', u
'\"', u
'#', u
'$', u
'%', u
'&', u
'\'', u
'(', u
')', u
'*', u
'+', u
',', u
'-', u
'.', u
'/',
593 u
'0', u
'1', u
'2', u
'3', u
'4', u
'5', u
'6', u
'7', u
'8', u
'9', u
':', u
';', u
'<', u
'=', u
'>', u
'?',
594 u
'@', u
'A', u
'B', u
'C', u
'D', u
'E', u
'F', u
'G', u
'H', u
'I', u
'J', u
'K', u
'L', u
'M', u
'N', u
'O',
595 u
'P', u
'Q', u
'R', u
'S', u
'T', u
'U', u
'V', u
'W', u
'X', u
'Y', u
'Z', u
'[', u
'\\', u
']', u
'^', u
'_',
596 u
'`', u
'a', u
'b', u
'c', u
'd', u
'e', u
'f', u
'g', u
'h', u
'i', u
'j', u
'k', u
'l', u
'm', u
'n', u
'o',
597 u
'p', u
'q', u
'r', u
's', u
't', u
'u', u
'v', u
'w', u
'x', u
'y', u
'z', u
'{', u
'|', u
'}', u
'~', u
' ',
598 u
'\u20AC', u
' ', u
'\u201A', u
' ', u
'\u201E', u
'\u2026', u
'\u2020', u
'\u2021', u
' ', u
'\u2030', u
'\u0160', u
'\u2039', u
'\u015A', u
'\u0164', u
'\u017D', u
'\u0179',
599 u
' ', u
'\u2018', u
'\u2019', u
'\u201C', u
'\u201D', u
'\u2022', u
'\u2013', u
'\u2014', u
' ', u
'\u2122', u
'\u0161',
600 u
'\u203A', u
'\u015B', u
'\u0165', u
'\u017E', u
'\u017A',
601 u
'\u00A0', u
'\u02C7', u
'\u02D8', u
'\u00A2', u
'\u00A3', u
'\u0104', u
'\u00A6', u
'\u00A7', u
'\u00A8', u
'\u00A9',
602 u
'\u015E', u
'\u00AB', u
'\u00AC', u
'-', u
'\u00AE', u
'\u017B',
603 u
'\u00B0', u
'\u00B1', u
'\u02DB', u
'\u0142', u
'\u00B4', u
'\u00B5', u
'\u00B6', u
'\u00B7', u
'\u00B8', u
'\u0105',
604 u
'\u015F', u
'\u00BB', u
'\u013D', u
'\u02DD', u
'\u013E', u
'\u017C',
605 u
'\u0154', u
'\u00C1', u
'\u00C2', u
'\u0102', u
'\u00C4', u
'\u0139', u
'\u0106', u
'\u00C7', u
'\u010C', u
'\u00C9',
606 u
'\u0118', u
'\u00CB', u
'\u011A', u
'\u00CD', u
'\u00CE', u
'\u010E',
607 u
'\u0110', u
'\u0143', u
'\u0147', u
'\u00D3', u
'\u00D4', u
'\u0150', u
'\u00D6', u
'\u00D7', u
'\u0158', u
'\u016E',
608 u
'\u00DA', u
'\u0170', u
'\u00DC', u
'\u00DD', u
'\u0162', u
'\u00DF',
609 u
'\u0115', u
'\u00E1', u
'\u00E2', u
'\u0103', u
'\u00E4', u
'\u013A', u
'\u0107', u
'\u00E7', u
'\u00E8', u
'\u00E9',
610 u
'\u0119', u
'\u00EB', u
'\u011B', u
'\u00ED', u
'\u00EE', u
'\u010F',
611 u
'\u0111', u
'\u0144', u
'\u0148', u
'\u00F3', u
'\u00F4', u
'\u0151', u
'\u00F6', u
'\u00F7', u
'\u0159', u
'\u016F',
612 u
'\u00FA', u
'\u0171', u
'\u00FC', u
'\u00FD', u
'\u0163', u
'\u02D9'};
624 if(
auto it =
state.locale_key_to_text_sequence.find(
id); it !=
state.locale_key_to_text_sequence.end()) {
625 sv =
state.locale_string_view(it->second);
627 sv =
state.to_string_view(
id);
630 char const* section_start = sv.data();
631 for(
char const* pos = sv.data(); pos < sv.data() + sv.length();) {
632 bool colour_esc =
false;
633 if(pos + 1 < sv.data() + sv.length() &&
uint8_t(*pos) == 0xC2 &&
uint8_t(*(pos + 1)) == 0xA7) {
634 if(section_start < pos)
635 result += std::string_view(section_start, pos - section_start);
639 if(pos < sv.data() + sv.length()) {
644 if(section_start < pos)
645 result += std::string_view(section_start, pos - section_start);
647 section_start = pos += 3;
649 if(pos < sv.data() + sv.length()) {
653 }
else if(pos + 1 < sv.data() + sv.length() && *pos ==
'?' &&
is_qmark_color(*(pos + 1))) {
654 if(section_start < pos)
655 result += std::string_view(section_start, pos - section_start);
660 if(pos < sv.data() + sv.length()) {
664 }
else if(*pos ==
'$') {
665 if(section_start < pos)
666 result += std::string_view(section_start, pos - section_start);
668 const char* vend = pos + 1;
669 for(; vend != sv.data() + sv.length() && *vend !=
'$'; ++vend)
674 }
else if(pos + 1 < sv.data() + sv.length() && *pos ==
'\\' && *(pos + 1) ==
'n') {
675 result += std::string_view(section_start, pos - section_start);
676 section_start = pos += 2;
682 if(section_start < sv.data() + sv.length())
683 result += std::string_view(section_start, (sv.data() + sv.length()) - section_start);
688 auto v =
state.lookup_key(txt);
692 return std::string(txt);
697 return state.add_key_utf8(key);
699 return state.add_key_win1252(key);
703 constexpr static double mag[] = {
709 1'000'000'000'000'000.0,
710 1'000'000'000'000'000'000.0
712 constexpr static char const* sufx_two[] = {
721 constexpr static char const* sufx_one[] = {
730 constexpr static char const* sufx_zero[] = {
739 char buffer[200] = { 0 };
740 double dval = double(
num);
741 if(std::abs(dval) <= 1.f) {
742 snprintf(buffer,
sizeof(buffer), sufx_two[0],
float(dval));
743 return std::string(buffer);
745 for(
size_t i = std::extent_v<
decltype(mag)>; i-- > 0;) {
746 if(std::abs(dval) >= mag[i]) {
747 auto reduced = dval / mag[i];
748 if(std::abs(reduced) < 10.0) {
749 snprintf(buffer,
sizeof(buffer), sufx_two[i],
float(reduced));
750 }
else if(std::abs(reduced) < 100.0) {
751 snprintf(buffer,
sizeof(buffer), sufx_one[i],
float(reduced));
753 snprintf(buffer,
sizeof(buffer), sufx_zero[i],
float(reduced));
755 return std::string(buffer);
758 return std::string(
"#inf");
764 return std::string(
"0");
766 constexpr static double mag[] = {
772 1'000'000'000'000'000.0,
773 1'000'000'000'000'000'000.0
775 constexpr static char const* sufx_two[] = {
784 constexpr static char const* sufx_one[] = {
793 constexpr static char const* sufx_zero[] = {
803 char buffer[200] = { 0 };
804 double dval = double(
num);
805 for(
size_t i = std::extent_v<
decltype(mag)>; i-- > 0;) {
806 if(std::abs(dval) >= mag[i]) {
807 auto reduced = dval / mag[i];
808 if(std::abs(reduced) < 10.0) {
809 snprintf(buffer,
sizeof(buffer), sufx_two[i],
float(reduced));
810 }
else if(std::abs(reduced) < 100.0) {
811 snprintf(buffer,
sizeof(buffer), sufx_one[i],
float(reduced));
813 snprintf(buffer,
sizeof(buffer), sufx_zero[i],
float(reduced));
815 return std::string(buffer);
818 return std::string(
"#inf");
823 for(
auto st : fat_id.get_definition().get_abstract_state_membership()) {
824 if(
auto osm = st.get_province().get_state_membership().id; osm && fat_id.id != osm) {
825 if(!
state.key_is_localized(fat_id.get_definition().get_name())) {
832 if(!
state.key_is_localized(fat_id.get_definition().get_name()))
839 for(
auto st : fat_id.get_definition().get_abstract_state_membership()) {
840 if(
auto osm = st.get_province().get_state_membership().id; osm && fat_id.id != osm) {
842 if(!
state.key_is_localized(fat_id.get_definition().get_name())) {
843 if(!
state.key_is_localized(adj_id)) {
850 }
else if(!
state.key_is_localized(adj_id)) {
859 if(!
state.key_is_localized(fat_id.get_definition().get_name()))
866 auto state_instance_id = fat_id.get_state_membership().id;
867 if(state_instance_id) {
870 auto sdef = fat_id.get_abstract_state_membership_as_province().get_state();
871 if(!
state.key_is_localized(sdef.get_name())) {
872 auto lprovs = sdef.get_abstract_state_membership();
873 if(lprovs.begin() != lprovs.end())
881 auto ident =
state.world.nation_get_identity_from_identity_holder(
id);
882 auto gov_id =
state.world.nation_get_government_type(
id);
884 auto gname =
state.world.national_identity_get_government_name(
ident, gov_id);
885 if(
state.key_is_localized(gname))
888 return state.world.national_identity_get_name(
ident);
891 auto ident =
state.world.nation_get_identity_from_identity_holder(
id);
893 if(
auto k =
state.world.national_identity_get_government_adjective(
ident,
state.world.nation_get_government_type(
id));
state.key_is_localized(k)) {
896 return state.world.national_identity_get_adjective(
ident);
900 auto ident =
state.world.nation_get_identity_from_identity_holder(
n);
901 auto gov =
state.world.nation_get_government_type(
n);
903 if(
auto k =
state.world.national_identity_get_government_ruler_name(
ident,
gov);
state.key_is_localized(k)) {
906 return state.world.government_type_get_ruler_name(
gov);
982 char buffer[200] = {0};
988 return std::string(
"0.000");
989 }
else if(
num > 0.f &&
num < 0.001f) {
990 return std::string(
">0.000");
991 }
else if(
num > -0.001f &&
num < 0.f) {
992 return std::string(
"<0.000");
998 return std::string(
"0.00");
999 }
else if(
num > 0.f &&
num < 0.01f) {
1000 return std::string(
">0.00");
1001 }
else if(
num > -0.01f &&
num < 0.f) {
1002 return std::string(
"<0.00");
1008 return std::string(
"0.0");
1009 }
else if(
num > 0.f &&
num < 0.1f) {
1010 return std::string(
">0.0");
1011 }
else if(
num > -0.1f &&
num < 0.f) {
1012 return std::string(
"<0.0");
1018 return std::string(
"0");
1019 }
else if(
num > 0.f &&
num < 1.f) {
1020 return std::string(
">0");
1021 }
else if(
num > -1.f &&
num < 0.f) {
1022 return std::string(
"<0");
1024 return std::to_string(int64_t(
num));
1026 return std::string(buffer);
1044 while(abs_value > 0) {
1048 auto last = abs_value % 10;
1051 result.push_back(
char(
'0' + last));
1065 return std::to_string(
left) +
'/' + std::to_string(
right);
1073 static const std::string_view month_names[12] = {
"january",
"february",
"march",
"april",
"may_month_name",
"june",
"july",
"august",
1074 "september",
"october",
"november",
"december"};
1077 return state.lookup_key(
"january");
1079 return state.lookup_key(month_names[
month - 1]);
1093 if(int32_t(chunk.x) <=
x &&
x <= int32_t(chunk.x) + chunk.width && chunk.y <=
y &&
y <= chunk.y + chunk.height) {
1101 dest.contents.clear();
1102 dest.number_of_lines = 0;
1112 auto gap = (box.
x_position - float(
dest.fixed_parameters.left)) / 2.0f;
1113 for(
size_t i = box.
line_start; i <
dest.base_layout.contents.size(); ++i) {
1114 dest.base_layout.contents[i].x -= gap;
1117 auto gap = (float(
dest.fixed_parameters.right) - box.
x_position) / 2.0f;
1118 for(
size_t i = box.
line_start; i <
dest.base_layout.contents.size(); ++i) {
1119 dest.base_layout.contents[i].x += gap;
1124 for(
size_t i = box.
line_start; i <
dest.base_layout.contents.size(); ++i) {
1125 dest.base_layout.contents[i].x += gap;
1129 for(
size_t i = box.
line_start; i <
dest.base_layout.contents.size(); ++i) {
1130 dest.base_layout.contents[i].x -= gap;
1141 dest.base_layout.number_of_lines += 1;
1148 auto text_height = int32_t(std::ceil(
state.font_collection.line_height(
state,
dest.fixed_parameters.font_id)));
1149 auto line_height = text_height +
dest.fixed_parameters.leading;
1153 auto text_height = int32_t(std::ceil(
state.font_collection.line_height(
state,
dest.fixed_parameters.font_id)));
1154 auto line_height = text_height +
dest.fixed_parameters.leading;
1155 dest.base_layout.number_of_lines += 1;
1156 dest.y_cursor += line_height;
1159 auto text_height = int32_t(std::ceil(
state.font_collection.line_height(
state,
dest.fixed_parameters.font_id)));
1160 auto line_height = text_height +
dest.fixed_parameters.leading;
1161 dest.base_layout.number_of_lines += 1;
1162 dest.y_cursor += line_height;
1245 if(
text.size() == 0)
1249 auto text_height = int32_t(std::ceil(
state.font_collection.line_height(
state,
dest.fixed_parameters.font_id)));
1250 auto line_height = text_height +
dest.fixed_parameters.leading;
1251 auto tmp_color = color;
1252 if(std::holds_alternative<dcon::nation_id>(
source)
1253 || std::holds_alternative<dcon::province_id>(
source)
1254 || std::holds_alternative<dcon::state_instance_id>(
source)
1255 || std::holds_alternative<dcon::state_definition_id>(
source)) {
1256 if(!
dest.fixed_parameters.suppress_hyperlinks) {
1271 bool first_in_line =
true;
1274 std::vector<uint16_t> temp_text;
1276 auto start =
text.data();
1277 auto end = start +
text.length();
1278 int32_t base_index = 0;
1280 while(start + base_index < end) {
1284 temp_text.push_back(
char16_t(c));
1287 temp_text.push_back(
char16_t(p.high));
1288 temp_text.push_back(
char16_t(p.low));
1295 UErrorCode errorCode = U_ZERO_ERROR;
1296 UBreakIterator* lb_it = ubrk_openBinaryRules(
state.font_collection.compiled_ubrk_rules.data(), int32_t(
state.font_collection.compiled_ubrk_rules.size()), (UChar
const*)temp_text.data(), int32_t(temp_text.size()), &errorCode);
1298 if(!lb_it || !U_SUCCESS(errorCode)) {
1307 int32_t glyph_position = 0;
1308 int32_t glyph_start_position = 0;
1309 int32_t cluster_position = 0;
1310 int32_t cluster_start_position = 0;
1312 while(cluster_start_position < int32_t(temp_text.size())) {
1313 if(
dest.fixed_parameters.single_line && box.
x_position <=
dest.fixed_parameters.left)
1316 auto next_cluster_position = ubrk_next(lb_it);
1317 int32_t next_glyph_position = 0;
1319 if(next_cluster_position == UBRK_DONE) {
1320 next_glyph_position = int32_t(all_glyphs.
glyph_info.size());
1321 next_cluster_position = int32_t(temp_text.size());
1323 for(next_glyph_position = glyph_position; next_glyph_position < int32_t(all_glyphs.
glyph_info.size()); ++next_glyph_position) {
1324 if(all_glyphs.
glyph_info[next_glyph_position].cluster >=
uint32_t(next_cluster_position)) {
1330 float extent =
state.font_collection.text_extent(
state, all_glyphs, glyph_start_position, next_glyph_position - glyph_start_position,
dest.fixed_parameters.font_id);
1341 box.
x_position, (!
dest.fixed_parameters.suppress_hyperlinks) ?
source : std::monostate{}, int16_t(box.
y_position), int16_t(extent), int16_t(text_height), tmp_color });
1346 glyph_start_position = next_glyph_position;
1347 glyph_position = next_glyph_position;
1348 cluster_position = next_cluster_position;
1349 cluster_start_position = next_cluster_position;
1350 }
else if(!
dest.fixed_parameters.single_line && box.
x_position - extent <=
dest.fixed_parameters.left) {
1351 extent =
state.font_collection.text_extent(
state, all_glyphs, glyph_start_position, glyph_position - glyph_start_position,
dest.fixed_parameters.font_id);
1356 dest.base_layout.contents.push_back(
1358 box.
x_position, (!
dest.fixed_parameters.suppress_hyperlinks) ?
source : std::monostate{}, int16_t(box.
y_position), int16_t(extent), int16_t(text_height), tmp_color });
1362 glyph_start_position = glyph_position;
1363 cluster_start_position = cluster_position;
1365 ubrk_previous(lb_it);
1366 first_in_line =
true;
1367 }
else if(
dest.fixed_parameters.single_line && box.
x_position - extent <=
dest.fixed_parameters.left) {
1370 bool ellipsis_valid =
true;
1373 if(width_of_ellipsis <= 0 || glyphid == 0) {
1374 ellipsis_valid =
false;
1377 if(
state.user_settings.use_classic_fonts) {
1378 ellipsis_valid =
false;
1379 width_of_ellipsis = 3.0f *
font_size / 6.f;
1382 int32_t
m = glyph_start_position;
1383 while(
m < next_glyph_position) {
1384 if(box.
x_position -
state.font_collection.text_extent(
state, all_glyphs, glyph_start_position,
uint32_t(
m),
dest.fixed_parameters.font_id) - width_of_ellipsis <
dest.fixed_parameters.left)
1388 if(
m >= next_glyph_position)
m = next_glyph_position - 1;
1390 auto cluster_end = all_glyphs.
glyph_info[
m].cluster;
1391 std::vector<uint16_t> tempv{ temp_text.data() + cluster_start_position, temp_text.data() + cluster_end };
1393 if(ellipsis_valid) {
1394 tempv.push_back(0x2026);
1396 tempv.push_back(
'.'); tempv.push_back(
'.'); tempv.push_back(
'.');
1399 dest.base_layout.contents.push_back(
1401 box.
x_position, (!
dest.fixed_parameters.suppress_hyperlinks) ?
source : std::monostate{}, int16_t(box.
y_position), int16_t(extent), int16_t(text_height), tmp_color });
1405 }
else if(next_cluster_position >= int32_t(temp_text.size())) {
1414 box.
x_position, (!
dest.fixed_parameters.suppress_hyperlinks) ?
source : std::monostate{}, int16_t(box.
y_position), int16_t(extent), int16_t(text_height), tmp_color });
1416 if(!
dest.fixed_parameters.single_line && box.
x_position <=
dest.fixed_parameters.left)
1419 glyph_start_position = next_glyph_position;
1420 glyph_position = next_glyph_position;
1421 cluster_position = next_cluster_position;
1422 cluster_start_position = next_cluster_position;
1424 glyph_position = next_glyph_position;
1425 cluster_position = next_cluster_position;
1426 first_in_line =
false;
1431 int32_t glyph_position = 0;
1432 int32_t glyph_start_position = 0;
1433 int32_t cluster_position = 0;
1434 int32_t cluster_start_position = 0;
1436 while(cluster_start_position < int32_t(temp_text.size())) {
1437 if(
dest.fixed_parameters.single_line && box.
x_position >=
dest.fixed_parameters.right)
1440 auto next_cluster_position = ubrk_next(lb_it);
1441 int32_t next_glyph_position = 0;
1443 if(next_cluster_position == UBRK_DONE) {
1444 next_glyph_position = int32_t(all_glyphs.
glyph_info.size());
1445 next_cluster_position = int32_t(temp_text.size());
1447 for(next_glyph_position = glyph_position; next_glyph_position < int32_t(all_glyphs.
glyph_info.size()); ++next_glyph_position) {
1448 if(all_glyphs.
glyph_info[next_glyph_position].cluster >=
uint32_t(next_cluster_position)) {
1454 float extent =
state.font_collection.text_extent(
state, all_glyphs, glyph_start_position, next_glyph_position - glyph_start_position,
dest.fixed_parameters.font_id);
1459 dest.base_layout.contents.push_back(
text_chunk{
text::stored_glyphs(
state,
text::font_index_from_font_id(
state,
dest.fixed_parameters.font_id), std::span<uint16_t>(temp_text.data() + cluster_start_position, next_cluster_position - cluster_start_position)), box.
x_position, (!
dest.fixed_parameters.suppress_hyperlinks) ?
source : std::monostate{}, int16_t(box.
y_position), int16_t(extent), int16_t(text_height), tmp_color });
1468 glyph_start_position = next_glyph_position;
1469 glyph_position = next_glyph_position;
1470 cluster_position = next_cluster_position;
1471 cluster_start_position = next_cluster_position;
1472 }
else if(!
dest.fixed_parameters.single_line && box.
x_position + extent >=
dest.fixed_parameters.right) {
1474 extent =
state.font_collection.text_extent(
state, all_glyphs, glyph_start_position, glyph_position - glyph_start_position,
dest.fixed_parameters.font_id);
1475 dest.base_layout.contents.push_back(
1477 box.
x_position, (!
dest.fixed_parameters.suppress_hyperlinks) ?
source : std::monostate{}, int16_t(box.
y_position), int16_t(extent), int16_t(text_height), tmp_color });
1484 glyph_start_position = glyph_position;
1485 cluster_start_position = cluster_position;
1487 ubrk_previous(lb_it);
1488 first_in_line =
true;
1489 }
else if(
dest.fixed_parameters.single_line && box.
x_position + extent >=
dest.fixed_parameters.right) {
1492 bool ellipsis_valid =
true;
1495 if(width_of_ellipsis <= 0 || glyphid == 0) {
1496 ellipsis_valid =
false;
1499 if(
state.user_settings.use_classic_fonts) {
1500 ellipsis_valid =
false;
1501 width_of_ellipsis = 3.0f *
font_size / 6.f;
1504 int32_t
m = glyph_start_position;
1505 while(
m < next_glyph_position) {
1506 if(box.
x_position +
state.font_collection.text_extent(
state, all_glyphs, glyph_start_position,
uint32_t(
m),
dest.fixed_parameters.font_id) + width_of_ellipsis >
dest.fixed_parameters.right)
1510 if(
m >= next_glyph_position)
m = next_glyph_position - 1;
1512 auto cluster_end = all_glyphs.
glyph_info[
m].cluster;
1513 std::vector<uint16_t> tempv{temp_text.data() + cluster_start_position, temp_text.data() + cluster_end };
1515 if(ellipsis_valid) {
1516 tempv.push_back(0x2026);
1518 tempv.push_back(
'.'); tempv.push_back(
'.'); tempv.push_back(
'.');
1521 dest.base_layout.contents.push_back(
1523 box.
x_position, (!
dest.fixed_parameters.suppress_hyperlinks) ?
source : std::monostate{}, int16_t(box.
y_position), int16_t(extent), int16_t(text_height), tmp_color });
1527 }
else if(next_cluster_position >= int32_t(temp_text.size())) {
1530 dest.base_layout.contents.push_back(
text_chunk{
text::stored_glyphs(
state,
text::font_index_from_font_id(
state,
dest.fixed_parameters.font_id), std::span<uint16_t>(temp_text.data() + cluster_start_position, next_cluster_position - cluster_start_position)), box.
x_position, (!
dest.fixed_parameters.suppress_hyperlinks) ?
source : std::monostate{}, int16_t(box.
y_position), int16_t(extent), int16_t(text_height), tmp_color });
1536 if(!
dest.fixed_parameters.single_line && box.
x_position >=
dest.fixed_parameters.right)
1539 glyph_start_position = next_glyph_position;
1540 glyph_position = next_glyph_position;
1541 cluster_position = next_cluster_position;
1542 cluster_start_position = next_cluster_position;
1544 glyph_position = next_glyph_position;
1545 cluster_position = next_cluster_position;
1546 first_in_line =
false;
1557 if(std::holds_alternative<std::string_view>(
sub)) {
1558 return std::string(std::get<std::string_view>(
sub));
1559 }
else if(std::holds_alternative<dcon::text_key>(
sub)) {
1560 auto tkey = std::get<dcon::text_key>(
sub);
1561 if(
auto it =
state.locale_key_to_text_sequence.find(tkey); it !=
state.locale_key_to_text_sequence.end()) {
1562 return std::string(
state.locale_string_view(it->second));
1564 return std::string(
state.to_string_view(tkey));
1566 }
else if(std::holds_alternative<dcon::nation_id>(
sub)) {
1567 dcon::nation_id nid = std::get<dcon::nation_id>(
sub);
1569 }
else if(std::holds_alternative<dcon::state_instance_id>(
sub)) {
1570 dcon::state_instance_id sid = std::get<dcon::state_instance_id>(
sub);
1572 }
else if(std::holds_alternative<dcon::province_id>(
sub)) {
1573 auto pid = std::get<dcon::province_id>(
sub);
1575 }
else if(std::holds_alternative<dcon::national_identity_id>(
sub)) {
1576 auto t = std::get<dcon::national_identity_id>(
sub);
1577 auto h =
state.world.national_identity_get_nation_from_identity_holder(t);
1579 }
else if(std::holds_alternative<int64_t>(
sub)) {
1580 return std::to_string(std::get<int64_t>(
sub));
1581 }
else if(std::holds_alternative<fp_one_place>(
sub)) {
1583 }
else if(std::holds_alternative<fp_two_places>(
sub)) {
1585 }
else if(std::holds_alternative<fp_three_places>(
sub)) {
1587 }
else if(std::holds_alternative<fp_four_places>(
sub)) {
1589 }
else if(std::holds_alternative<sys::date>(
sub)) {
1591 }
else if(std::holds_alternative<fp_currency>(
sub)) {
1593 }
else if(std::holds_alternative<pretty_integer>(
sub)) {
1595 }
else if(std::holds_alternative<fp_percentage>(
sub)) {
1597 }
else if(std::holds_alternative<fp_percentage_one_place>(
sub)) {
1599 }
else if(std::holds_alternative<int_percentage>(
sub)) {
1600 return std::to_string(std::get<int_percentage>(
sub).
value) +
"%";
1601 }
else if(std::holds_alternative<int_wholenum>(
sub)) {
1603 }
else if(std::holds_alternative<dcon::state_definition_id>(
sub)) {
1606 return std::string(
"?");
1613 if(sv.length() == 0)
1616 auto current_color =
dest.fixed_parameters.color;
1618 auto text_height = int32_t(std::ceil(
state.font_collection.line_height(
state,
dest.fixed_parameters.font_id)));
1619 auto line_height = text_height +
dest.fixed_parameters.leading;
1621 char const* seq_start = sv.data();
1622 char const* seq_end = sv.data() + sv.size();
1623 char const* section_start = seq_start;
1625 auto add_text_range = [&](std::string_view sv) {
1626 if(sv.length() > 0) {
1631 for(
char const* pos = seq_start; pos < seq_end;) {
1632 bool colour_esc =
false;
1633 if(pos + 1 < seq_end &&
uint8_t(*pos) == 0xC2 &&
uint8_t(*(pos + 1)) == 0xA7) {
1634 if(section_start < pos)
1635 add_text_range(std::string_view(section_start, pos - section_start));
1638 section_start = pos;
1642 current_color =
dest.fixed_parameters.color;
1644 current_color = newcolor;
1647 section_start = pos;
1650 if(section_start < pos)
1651 add_text_range(std::string_view(section_start, pos - section_start));
1653 section_start = pos += 3;
1658 current_color =
dest.fixed_parameters.color;
1660 current_color = newcolor;
1663 section_start = pos;
1665 }
else if(*pos ==
'@' && pos + 3 < seq_end) {
1666 if(*(pos + 1) ==
'(' && *(pos + 3) ==
')') {
1667 if(*(pos + 2) ==
'A') {
1668 if(section_start < pos)
1669 add_text_range(std::string_view(section_start, pos - section_start));
1672 section_start = pos;
1673 }
else if(*(pos + 2) ==
'N') {
1674 if(section_start < pos)
1675 add_text_range(std::string_view(section_start, pos - section_start));
1678 section_start = pos;
1679 }
else if(*(pos + 2) ==
'T') {
1680 if(section_start < pos)
1681 add_text_range(std::string_view(section_start, pos - section_start));
1684 section_start = pos;
1685 }
else if(*(pos + 2) ==
'F') {
1686 if(section_start < pos)
1687 add_text_range(std::string_view(section_start, pos - section_start));
1690 section_start = pos;
1694 }
else if(*(pos + 1) ==
'*') {
1695 if(section_start < pos)
1696 add_text_range(std::string_view(section_start, pos - section_start));
1698 uint8_t tens = char(*(pos + 2)) -
'0';
1699 uint8_t ones = char(*(pos + 3)) -
'0';
1700 uint8_t unit_index = tens * 10 + ones;
1702 dcon::unit_type_id given_unit_type_id { unit_index };
1704 section_start = pos;
1705 }
else if(*(pos + 1) ==
'$') {
1706 if(section_start < pos)
1707 add_text_range(std::string_view(section_start, pos - section_start));
1709 uint8_t tens = char(*(pos + 2)) -
'0';
1710 uint8_t ones = char(*(pos + 3)) -
'0';
1711 uint8_t commodity_index = tens * 10 + ones;
1713 dcon::commodity_id cid{ commodity_index };
1715 section_start = pos;
1717 auto tag_int =
nations::tag_to_int(
char(toupper(*(pos + 1))),
char(toupper(*(pos + 2))),
char(toupper(*(pos + 3))));
1718 bool matched =
false;
1719 for(
auto nid :
state.world.in_national_identity) {
1720 if(nid.get_identifying_int() == tag_int) {
1723 if(section_start < pos)
1724 add_text_range(std::string_view(section_start, pos - section_start));
1729 section_start = pos;
1736 }
else if(pos + 1 < seq_end && *pos ==
'?' &&
is_qmark_color(*(pos + 1))) {
1737 if(section_start < pos)
1738 add_text_range(std::string_view(section_start, pos - section_start));
1741 section_start = pos;
1748 current_color =
dest.fixed_parameters.color;
1750 current_color = newcolor;
1753 section_start = pos;
1755 }
else if(*pos ==
'$') {
1756 if(section_start < pos)
1757 add_text_range(std::string_view(section_start, pos - section_start));
1759 const char* vend = pos + 1;
1760 for(; vend != seq_end && *vend !=
'$'; ++vend)
1762 if(vend > pos + 1) {
1765 if(
auto it = mp.find(
uint32_t(var_type)); it != mp.end()) {
1776 section_start = pos;
1777 }
else if(pos + 1 < seq_end && *pos ==
'\\' && *(pos + 1) ==
'n') {
1778 if(section_start < pos)
1779 add_text_range(std::string_view(section_start, pos - section_start));
1782 section_start = pos += 2;
1788 if(section_start < seq_end)
1789 add_text_range(std::string_view(section_start, seq_end - section_start));
1796 std::string_view sv;
1797 if(
auto it =
state.locale_key_to_text_sequence.find(source_text); it !=
state.locale_key_to_text_sequence.end()) {
1798 sv =
state.locale_string_view(it->second);
1800 sv =
state.to_string_view(source_text);
1825 return layout_box{
dest.base_layout.contents.size(),
dest.base_layout.contents.size(), indent, 0, 0,
1826 float(indent +
dest.fixed_parameters.left), 0,
dest.fixed_parameters.color};
1828 return layout_box{
dest.base_layout.contents.size(),
dest.base_layout.contents.size(), indent, 0, 0,
1829 float(
dest.fixed_parameters.right - indent), 0,
dest.fixed_parameters.color };
1835 dest.current_column_x =
dest.used_width +
dest.column_width;
1836 for(
auto i = box.
first_chunk; i <
dest.base_layout.contents.size(); ++i) {
1837 dest.base_layout.contents[i].y +=
dest.fixed_parameters.top;
1838 dest.base_layout.contents[i].x += float(
dest.current_column_x);
1839 dest.used_width = std::max(
dest.used_width, int32_t(
dest.base_layout.contents[i].x +
dest.base_layout.contents[i].width));
1843 for(
auto i = box.
first_chunk; i <
dest.base_layout.contents.size(); ++i) {
1844 dest.base_layout.contents[i].y += int16_t(
dest.y_cursor);
1845 dest.base_layout.contents[i].x += float(
dest.current_column_x);
1846 dest.used_width = std::max(
dest.used_width, int32_t(
dest.base_layout.contents[i].x +
dest.base_layout.contents[i].width));
1850 dest.used_height = std::max(
dest.used_height,
dest.y_cursor);
1853 dest.current_column_x =
dest.used_width -
dest.column_width;
1854 for(
auto i = box.
first_chunk; i <
dest.base_layout.contents.size(); ++i) {
1855 dest.base_layout.contents[i].y +=
dest.fixed_parameters.top;
1856 dest.base_layout.contents[i].x += float(
dest.current_column_x) - float(
dest.fixed_parameters.right -
dest.fixed_parameters.left);
1857 dest.used_width = std::min(
dest.used_width, int32_t(
dest.base_layout.contents[i].x));
1861 for(
auto i = box.
first_chunk; i <
dest.base_layout.contents.size(); ++i) {
1862 dest.base_layout.contents[i].y += int16_t(
dest.y_cursor);
1863 dest.base_layout.contents[i].x += float(
dest.current_column_x) - float(
dest.fixed_parameters.right -
dest.fixed_parameters.left);
1864 dest.used_width = std::min(
dest.used_width, int32_t(
dest.base_layout.contents[i].x));
1868 dest.used_height = std::max(
dest.used_height,
dest.y_cursor);
1873 for(
auto i = box.
first_chunk; i <
dest.base_layout.contents.size(); ++i) {
1874 dest.base_layout.contents[i].y += int16_t(
dest.y_cursor);
1884 dest.internal_close_box(box);
1898 dest.contents.clear();
1899 dest.number_of_lines = 0;
1905 if(
auto k =
state.lookup_key(key); k) {
1916 if(
auto k =
state.lookup_key(key); k) {
1972 if(
auto k =
state.lookup_key(key); k) {
1990 if(
auto k =
state.lookup_key(key); k) {
2008 if(
auto k =
state.lookup_key(key); k) {
2028 if(
auto k =
state.lookup_key(key); k) {
2038void add_line_with_condition(
sys::state&
state,
layout_base&
dest, std::string_view key,
bool condition_met,
variable_type subkey,
substitution value,
variable_type subkeyb,
substitution valueb,
variable_type subkeyc,
substitution valuec, int32_t indent) {
2049 if(
auto k =
state.lookup_key(key); k) {
2064 if(
auto k =
state.lookup_key(key); k) {
2077 if(
auto k =
state.lookup_key(key); k) {
2091 if(
auto k =
state.lookup_key(key); k) {
2107 if(
auto k =
state.lookup_key(key); k) {
2130 auto ident =
state.world.nation_get_identity_from_identity_holder(
n);
2140 std::string_view sv;
2141 if(
auto it =
state.locale_key_to_text_sequence.find(source_text); it !=
state.locale_key_to_text_sequence.end()) {
2142 sv =
state.locale_string_view(it->second);
2144 sv =
state.to_string_view(source_text);
2147 char const* seq_start = sv.data();
2148 char const* seq_end = sv.data() + sv.size();
2149 char const* section_start = seq_start;
2151 auto add_text_range = [&](std::string_view sv) {
2155 for(
char const* pos = seq_start; pos < seq_end;) {
2156 bool colour_esc =
false;
2157 if(pos + 1 < seq_end &&
uint8_t(*pos) == 0xC2 &&
uint8_t(*(pos + 1)) == 0xA7) {
2158 if(section_start < pos)
2159 add_text_range(std::string_view(section_start, pos - section_start));
2162 section_start = pos;
2165 section_start = pos;
2168 if(section_start < pos)
2169 add_text_range(std::string_view(section_start, pos - section_start));
2171 section_start = pos += 3;
2175 section_start = pos;
2177 }
else if(pos + 1 < seq_end && *pos ==
'?' &&
is_qmark_color(*(pos + 1))) {
2178 if(section_start < pos)
2179 add_text_range(std::string_view(section_start, pos - section_start));
2182 section_start = pos;
2186 section_start = pos;
2188 }
else if(*pos ==
'$') {
2189 if(section_start < pos)
2190 add_text_range(std::string_view(section_start, pos - section_start));
2192 const char* vend = pos + 1;
2193 for(; vend != seq_end && *vend !=
'$'; ++vend)
2195 if(vend > pos + 1) {
2198 if(
auto it = mp.find(
uint32_t(var_type)); it != mp.end()) {
2204 result += std::string_view(pos, (vend - pos) + 1);
2208 section_start = pos;
2209 }
else if(pos + 1 < seq_end && *pos ==
'\\' && *(pos + 1) ==
'n') {
2210 add_text_range(std::string_view(section_start, pos - section_start));
2211 section_start = pos += 2;
2217 if(section_start < seq_end)
2218 add_text_range(std::string_view(section_start, seq_end - section_start));
2224 dcon::text_key source_text;
2225 if(
auto k =
state.lookup_key(key); k) {
2230 return std::string{key};
float base_glyph_width(char32_t ch_in)
pop_satisfaction_wrapper_fat fatten(data_container const &c, pop_satisfaction_wrapper_id id) noexcept
constexpr uint8_t level_friendly
constexpr uint8_t level_opposed
constexpr uint8_t level_neutral
constexpr uint8_t level_hostile
constexpr uint8_t level_in_sphere
constexpr uint8_t level_mask
constexpr uint8_t level_cordial
@ immigration_colonization_focus
uint32_t tag_to_int(char first, char second, char third)
std::string lb_resolve_substitution(sys::state &state, substitution sub, substitution_map const &mp)
void lb_finish_line(layout_base &dest, layout_box &box, int32_t line_height)
@ crisisdefender_continent
@ error_no_matching_value
@ crisisattacker_continent
void add_line_break_to_layout_box(sys::state &state, layout_base &dest, layout_box &box)
void add_to_layout_box(sys::state &state, layout_base &dest, layout_box &box, embedded_flag ico)
std::string resolve_string_substitution(sys::state &state, dcon::text_key source_text, substitution_map const &mp)
std::string format_money(float num)
std::string get_focus_category_name(sys::state const &state, nations::focus_type category)
int32_t size_from_font_id(uint16_t id)
std::string get_name_as_string(sys::state &state, T t)
std::string format_ratio(int32_t left, int32_t right)
layout_box open_layout_box(layout_base &dest, int32_t indent)
bool codepoint_is_space(uint32_t c) noexcept
void add_unparsed_text_to_layout_box(sys::state &state, layout_base &dest, layout_box &box, std::string_view sv, substitution_map const &mp)
bool codepoint_is_line_break(uint32_t c) noexcept
columnar_layout create_columnar_layout(sys::state &state, layout &dest, layout_parameters const ¶ms, int32_t column_width)
std::string date_to_string(sys::state &state, sys::date date)
void localised_single_sub_box(sys::state &state, layout_base &dest, layout_box &box, std::string_view key, variable_type subkey, substitution value)
void localised_format_box(sys::state &state, layout_base &dest, layout_box &box, std::string_view key, text::substitution_map const &sub)
std::string prettify(int64_t num)
endless_layout create_endless_layout(sys::state &state, layout &dest, layout_parameters const ¶ms)
std::string format_float(float num, size_t digits)
dcon::text_key get_ruler_title(sys::state &state, dcon::nation_id n)
void add_line(sys::state &state, layout_base &dest, dcon::text_key txt, int32_t indent)
std::string get_short_state_name(sys::state &state, dcon::state_instance_id state_id)
uint32_t codepoint_from_utf8(char const *start, char const *end)
void add_line_with_condition(sys::state &state, layout_base &dest, std::string_view key, bool condition_met, int32_t indent)
void add_line_break_to_layout(sys::state &state, columnar_layout &dest)
text::alignment to_text_alignment(ui::alignment in)
text_color char_to_color(char in)
std::string lowercase_str(std::string_view sv)
bool is_fixed_token_ci(std::string_view v, char const (&t)[N])
char16_t win1250toUTF16(char in)
void add_to_substitution_map(substitution_map &mp, variable_type key, substitution value)
surrogate_pair make_surrogate_pair(uint32_t val) noexcept
void add_divider_to_layout_box(sys::state &state, layout_base &dest, layout_box &box)
dcon::text_key get_adjective(sys::state &state, dcon::nation_id id)
std::string get_dynamic_state_name(sys::state &state, dcon::state_instance_id state_id)
std::string format_wholenum(int32_t num)
size_t size_from_utf8(char const *start, char const *)
ankerl::unordered_dense::map< uint32_t, substitution > substitution_map
bool requires_surrogate_pair(uint32_t codepoint)
std::string produce_simple_string(sys::state const &state, dcon::text_key id)
dcon::text_key get_name(sys::state &state, dcon::nation_id id)
font_selection font_index_from_font_id(sys::state &state, uint16_t id)
std::string format_percentage(float num, size_t digits)
void consume_csv_file(sys::state &state, char const *file_content, uint32_t file_size, int32_t target_column, bool as_unicode)
text::alignment localized_alignment(sys::state &state, text::alignment in)
std::string get_influence_level_name(sys::state const &state, uint8_t v)
variable_type variable_type_from_name(std::string_view v)
dcon::text_key localize_month(sys::state const &state, uint16_t month)
void add_space_to_layout_box(sys::state &state, layout_base &dest, layout_box &box)
void nation_name_and_flag(sys::state &state, dcon::nation_id n, layout_base &dest, int32_t indent)
std::string get_province_state_name(sys::state &state, dcon::province_id prov_id)
dcon::text_key find_or_add_key(sys::state &state, std::string_view key, bool as_unicode)
uint32_t font_size(std::string_view txt)
std::string prettify_currency(float num)
void close_layout_box(columnar_layout &dest, layout_box &box)
std::variant< std::string_view, dcon::text_key, dcon::province_id, dcon::state_instance_id, dcon::nation_id, dcon::national_identity_id, int64_t, fp_one_place, sys::date, std::monostate, fp_two_places, fp_three_places, fp_four_places, fp_currency, pretty_integer, fp_percentage, fp_percentage_one_place, int_percentage, int_wholenum, dcon::state_definition_id, embedded_icon, embedded_flag, embedded_unit_icon, embedded_commodity_icon > substitution
bool is_qmark_color(char in)
Holds important data about the game world, state, and other data regarding windowing,...
void internal_close_box(layout_box &box) final
void internal_close_box(layout_box &box) final
text_chunk const * get_chunk_from_position(int32_t x, int32_t y) const
std::vector< text_chunk > contents
void internal_close_box(layout_box &box) final
void add_text(sys::state &state, std::string_view v)
std::vector< stored_glyph > glyph_info
#define CT_STRING_ENUM(X)