virtual */
| 515 | |
| 516 | |
| 517 | /* virtual */ void UniscribeStringIterator::SetString(std::string_view s) |
| 518 | { |
| 519 | this->utf16_to_utf8.clear(); |
| 520 | this->str_info.clear(); |
| 521 | this->cur_pos = 0; |
| 522 | |
| 523 | /* Uniscribe operates on UTF-16, thus we have to convert the input string. |
| 524 | * To be able to return proper offsets, we have to create a mapping at the same time. */ |
| 525 | std::vector<wchar_t> utf16_str; ///< UTF-16 copy of the string. |
| 526 | Utf8View view(s); |
| 527 | for (auto it = view.begin(), end = view.end(); it != end; ++it) { |
| 528 | size_t idx = it.GetByteOffset(); |
| 529 | char32_t c = *it; |
| 530 | if (c < 0x10000) { |
| 531 | utf16_str.push_back((wchar_t)c); |
| 532 | } else { |
| 533 | /* Make a surrogate pair. */ |
| 534 | utf16_str.push_back((wchar_t)(0xD800 + ((c - 0x10000) >> 10))); |
| 535 | utf16_str.push_back((wchar_t)(0xDC00 + ((c - 0x10000) & 0x3FF))); |
| 536 | this->utf16_to_utf8.push_back(idx); |
| 537 | } |
| 538 | this->utf16_to_utf8.push_back(idx); |
| 539 | } |
| 540 | this->utf16_to_utf8.push_back(s.size()); |
| 541 | |
| 542 | /* Query Uniscribe for word and cluster break information. */ |
| 543 | this->str_info.resize(utf16_to_utf8.size()); |
| 544 | |
| 545 | if (!utf16_str.empty()) { |
| 546 | /* Itemize string into language runs. */ |
| 547 | std::vector<SCRIPT_ITEM> runs = UniscribeItemizeString(&utf16_str[0], (int32_t)utf16_str.size()); |
| 548 | |
| 549 | for (std::vector<SCRIPT_ITEM>::const_iterator run = runs.begin(); !runs.empty() && run != runs.end() - 1; run++) { |
| 550 | /* Get information on valid word and character break.s */ |
| 551 | int len = (run + 1)->iCharPos - run->iCharPos; |
| 552 | std::vector<SCRIPT_LOGATTR> attr(len); |
| 553 | ScriptBreak(&utf16_str[run->iCharPos], len, &run->a, &attr[0]); |
| 554 | |
| 555 | /* Extract the information we're interested in. */ |
| 556 | for (size_t c = 0; c < attr.size(); c++) { |
| 557 | /* First character of a run is always a valid word break. */ |
| 558 | this->str_info[c + run->iCharPos].word_stop = attr[c].fWordStop || c == 0; |
| 559 | this->str_info[c + run->iCharPos].char_stop = attr[c].fCharStop; |
| 560 | } |
| 561 | } |
| 562 | } |
| 563 | |
| 564 | /* End-of-string is always a valid stopping point. */ |
| 565 | this->str_info.back().char_stop = true; |
| 566 | this->str_info.back().word_stop = true; |
| 567 | } |
| 568 | |
| 569 | /* virtual */ size_t UniscribeStringIterator::SetCurPosition(size_t pos) |
| 570 | { |
nothing calls this directly
no test coverage detected