Line data Source code
1 : /**
2 : Copyright (c) 2024 Stappler LLC <admin@stappler.dev>
3 :
4 : Permission is hereby granted, free of charge, to any person obtaining a copy
5 : of this software and associated documentation files (the "Software"), to deal
6 : in the Software without restriction, including without limitation the rights
7 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 : copies of the Software, and to permit persons to whom the Software is
9 : furnished to do so, subject to the following conditions:
10 :
11 : The above copyright notice and this permission notice shall be included in
12 : all copies or substantial portions of the Software.
13 :
14 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 : THE SOFTWARE.
21 : **/
22 :
23 : #include "SPFontHyphenMap.h"
24 : #include "hyphen/hyphen.h"
25 :
26 : namespace STAPPLER_VERSIONIZED stappler::font {
27 :
28 0 : HyphenMap::~HyphenMap() {
29 0 : for (auto &it : _dicts) {
30 0 : hnj_hyphen_free(it.second);
31 : }
32 0 : }
33 0 : bool HyphenMap::init() {
34 0 : return true;
35 : }
36 :
37 0 : void HyphenMap::addHyphenDict(CharGroupId id, FilePath file) {
38 0 : auto data = filesystem::readTextFile<Interface>(file.get());
39 0 : if (!data.empty()) {
40 0 : auto dict = hnj_hyphen_load_data(data.data(), data.size());
41 0 : if (dict) {
42 0 : auto it = _dicts.find(id);
43 0 : if (it == _dicts.end()) {
44 0 : _dicts.emplace(id, dict);
45 : } else {
46 0 : hnj_hyphen_free(it->second);
47 0 : it->second = dict;
48 : }
49 : }
50 : }
51 0 : }
52 :
53 0 : void HyphenMap::addHyphenDict(CharGroupId id, BytesView data) {
54 0 : if (!data.empty()) {
55 0 : auto dict = hnj_hyphen_load_data((const char *)data.data(), data.size());
56 0 : if (dict) {
57 0 : auto it = _dicts.find(id);
58 0 : if (it == _dicts.end()) {
59 0 : _dicts.emplace(id, dict);
60 : } else {
61 0 : hnj_hyphen_free(it->second);
62 0 : it->second = dict;
63 : }
64 : }
65 : }
66 0 : }
67 :
68 0 : auto HyphenMap::makeWordHyphens(const char16_t *ptr, size_t len) -> Vector<uint8_t> {
69 0 : if (len < 4 || len >= 255) {
70 0 : return Vector<uint8_t>();
71 : }
72 :
73 0 : HyphenDict *dict = nullptr;
74 0 : for (auto &it : _dicts) {
75 0 : if (inCharGroup(it.first, ptr[0])) {
76 0 : dict = it.second;
77 0 : break;
78 : }
79 : }
80 :
81 0 : if (!dict) {
82 0 : return Vector<uint8_t>();
83 : }
84 :
85 0 : String word = convertWord(dict, ptr, len);
86 0 : if (!word.empty()) {
87 0 : Vector<char> buf; buf.resize(word.size() + 5);
88 :
89 0 : char ** rep = nullptr;
90 0 : int * pos = nullptr;
91 0 : int * cut = nullptr;
92 0 : hnj_hyphen_hyphenate2(dict, word.data(), int(word.size()), buf.data(), nullptr, &rep, &pos, &cut);
93 :
94 0 : Vector<uint8_t> ret;
95 0 : uint8_t i = 0;
96 0 : for (auto &it : buf) {
97 0 : if (it > 0) {
98 0 : if ((it - '0') % 2 == 1) {
99 0 : ret.push_back(i + 1);
100 : }
101 : } else {
102 0 : break;
103 : }
104 0 : ++ i;
105 : }
106 0 : return ret;
107 0 : }
108 0 : return Vector<uint8_t>();
109 0 : }
110 :
111 0 : auto HyphenMap::makeWordHyphens(const WideStringView &r) -> Vector<uint8_t> {
112 0 : return makeWordHyphens(r.data(), r.size());
113 : }
114 :
115 0 : void HyphenMap::purgeHyphenDicts() {
116 0 : for (auto &it : _dicts) {
117 0 : hnj_hyphen_free(it.second);
118 : }
119 0 : }
120 :
121 0 : auto HyphenMap::convertWord(HyphenDict *dict, const char16_t *ptr, size_t len) -> String {
122 0 : if (dict->utf8) {
123 0 : return string::toUtf8<Interface>(WideStringView(ptr, len));
124 : } else {
125 0 : if (strcmp("KOI8-R", dict->cset) == 0) {
126 0 : return string::toKoi8r<Interface>(WideStringView(ptr, len));
127 : }
128 :
129 0 : return String();
130 : }
131 : }
132 :
133 : }
|