1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 */
10
11 #include <font/OpenTypeFeatureDefinitionList.hxx>
12 #include <font/OpenTypeFeatureStrings.hrc>
13
14 #include <rtl/character.hxx>
15
16 #include <algorithm>
17
18 namespace vcl::font
19 {
OpenTypeFeatureDefinitionListPrivate()20 OpenTypeFeatureDefinitionListPrivate::OpenTypeFeatureDefinitionListPrivate() { init(); }
21
init()22 void OpenTypeFeatureDefinitionListPrivate::init()
23 {
24 m_aFeatureDefinition.assign({
25 { featureCode("aalt"), STR_FONT_FEATURE_ID_AALT },
26 { featureCode("afrc"), STR_FONT_FEATURE_ID_AFRC },
27 { featureCode("alig"), STR_FONT_FEATURE_ID_ALIG },
28 { featureCode("c2pc"), STR_FONT_FEATURE_ID_C2PC },
29 { featureCode("c2sc"), STR_FONT_FEATURE_ID_C2SC },
30 { featureCode("calt"), STR_FONT_FEATURE_ID_CALT },
31 { featureCode("case"), STR_FONT_FEATURE_ID_CASE },
32 { featureCode("clig"), STR_FONT_FEATURE_ID_CLIG },
33 { featureCode("cpct"), STR_FONT_FEATURE_ID_CPCT },
34 { featureCode("cpsp"), STR_FONT_FEATURE_ID_CPSP },
35 { featureCode("cswh"), STR_FONT_FEATURE_ID_CSWH },
36 { featureCode("dcap"), STR_FONT_FEATURE_ID_DCAP },
37 { featureCode("dlig"), STR_FONT_FEATURE_ID_DLIG },
38 { featureCode("dnom"), STR_FONT_FEATURE_ID_DNOM },
39 { featureCode("dpng"), STR_FONT_FEATURE_ID_DPNG },
40 { featureCode("expt"), STR_FONT_FEATURE_ID_EXPT },
41 { featureCode("falt"), STR_FONT_FEATURE_ID_FALT },
42 { featureCode("frac"), STR_FONT_FEATURE_ID_FRAC,
43 std::vector<FeatureParameter>{ { 0, STR_FONT_FEATURE_ID_FRAC_PARAM_0 },
44 { 1, STR_FONT_FEATURE_ID_FRAC_PARAM_1 },
45 { 2, STR_FONT_FEATURE_ID_FRAC_PARAM_2 } } },
46 { featureCode("fwid"), STR_FONT_FEATURE_ID_FWID },
47 { featureCode("halt"), STR_FONT_FEATURE_ID_HALT },
48 { featureCode("hist"), STR_FONT_FEATURE_ID_HIST },
49 { featureCode("hkna"), STR_FONT_FEATURE_ID_HKNA },
50 { featureCode("hlig"), STR_FONT_FEATURE_ID_HLIG },
51 { featureCode("hngl"), STR_FONT_FEATURE_ID_HNGL },
52 { featureCode("hojo"), STR_FONT_FEATURE_ID_HOJO },
53 { featureCode("hwid"), STR_FONT_FEATURE_ID_HWID },
54 { featureCode("ital"), STR_FONT_FEATURE_ID_ITAL },
55 { featureCode("jalt"), STR_FONT_FEATURE_ID_JALT },
56 { featureCode("jp78"), STR_FONT_FEATURE_ID_JP78 },
57 { featureCode("jp83"), STR_FONT_FEATURE_ID_JP83 },
58 { featureCode("jp90"), STR_FONT_FEATURE_ID_JP90 },
59 { featureCode("jp04"), STR_FONT_FEATURE_ID_JP04 },
60 { featureCode("kern"), STR_FONT_FEATURE_ID_KERN },
61 { featureCode("lfbd"), STR_FONT_FEATURE_ID_LFBD },
62 { featureCode("liga"), STR_FONT_FEATURE_ID_LIGA },
63 { featureCode("lnum"), STR_FONT_FEATURE_ID_LNUM },
64 { featureCode("mgrk"), STR_FONT_FEATURE_ID_MGRK },
65 { featureCode("nalt"), STR_FONT_FEATURE_ID_NALT },
66 { featureCode("nlck"), STR_FONT_FEATURE_ID_NLCK },
67 { featureCode("numr"), STR_FONT_FEATURE_ID_NUMR },
68 { featureCode("onum"), STR_FONT_FEATURE_ID_ONUM },
69 { featureCode("opbd"), STR_FONT_FEATURE_ID_OPBD },
70 { featureCode("ordn"), STR_FONT_FEATURE_ID_ORDN },
71 { featureCode("ornm"), STR_FONT_FEATURE_ID_ORNM },
72 { featureCode("palt"), STR_FONT_FEATURE_ID_PALT },
73 { featureCode("pcap"), STR_FONT_FEATURE_ID_PCAP },
74 { featureCode("pkna"), STR_FONT_FEATURE_ID_PKNA },
75 { featureCode("pnum"), STR_FONT_FEATURE_ID_PNUM },
76 { featureCode("pwid"), STR_FONT_FEATURE_ID_PWID },
77 { featureCode("qwid"), STR_FONT_FEATURE_ID_QWID },
78 { featureCode("rtbd"), STR_FONT_FEATURE_ID_RTBD },
79 { featureCode("ruby"), STR_FONT_FEATURE_ID_RUBY },
80 { featureCode("salt"), STR_FONT_FEATURE_ID_SALT },
81 { featureCode("sinf"), STR_FONT_FEATURE_ID_SINF },
82 { featureCode("smcp"), STR_FONT_FEATURE_ID_SMCP },
83 { featureCode("smpl"), STR_FONT_FEATURE_ID_SMPL },
84 { featureCode("subs"), STR_FONT_FEATURE_ID_SUBS },
85 { featureCode("sups"), STR_FONT_FEATURE_ID_SUPS },
86 { featureCode("swsh"), STR_FONT_FEATURE_ID_SWSH },
87 { featureCode("titl"), STR_FONT_FEATURE_ID_TITL },
88 { featureCode("tnam"), STR_FONT_FEATURE_ID_TNAM },
89 { featureCode("tnum"), STR_FONT_FEATURE_ID_TNUM },
90 { featureCode("trad"), STR_FONT_FEATURE_ID_TRAD },
91 { featureCode("twid"), STR_FONT_FEATURE_ID_TWID },
92 { featureCode("unic"), STR_FONT_FEATURE_ID_UNIC },
93 { featureCode("valt"), STR_FONT_FEATURE_ID_VALT },
94 { featureCode("vhal"), STR_FONT_FEATURE_ID_VHAL },
95 { featureCode("vkna"), STR_FONT_FEATURE_ID_VKNA },
96 { featureCode("vkrn"), STR_FONT_FEATURE_ID_VKRN },
97 { featureCode("vpal"), STR_FONT_FEATURE_ID_VPAL },
98 { featureCode("vrt2"), STR_FONT_FEATURE_ID_VRT2 },
99 { featureCode("vrtr"), STR_FONT_FEATURE_ID_VRTR },
100 { featureCode("zero"), STR_FONT_FEATURE_ID_ZERO },
101 });
102
103 for (size_t i = 0; i < m_aFeatureDefinition.size(); ++i)
104 {
105 m_aCodeToIndex.emplace(m_aFeatureDefinition[i].getCode(), i);
106 }
107
108 m_aRequiredFeatures.assign({
109 featureCode("abvf"), featureCode("abvm"), featureCode("abvs"), featureCode("akhn"),
110 featureCode("blwf"), featureCode("blwm"), featureCode("blws"), featureCode("ccmp"),
111 featureCode("cfar"), featureCode("cjct"), featureCode("curs"), featureCode("dist"),
112 featureCode("dtls"), featureCode("fin2"), featureCode("fin3"), featureCode("fina"),
113 featureCode("flac"), featureCode("half"), featureCode("haln"), featureCode("init"),
114 featureCode("isol"), featureCode("ljmo"), featureCode("locl"), featureCode("ltra"),
115 featureCode("ltrm"), featureCode("mark"), featureCode("med2"), featureCode("medi"),
116 featureCode("mkmk"), featureCode("mset"), featureCode("nukt"), featureCode("pref"),
117 featureCode("pres"), featureCode("pstf"), featureCode("psts"), featureCode("rand"),
118 featureCode("rclt"), featureCode("rkrf"), featureCode("rlig"), featureCode("rphf"),
119 featureCode("rtla"), featureCode("rtlm"), featureCode("rvrn"), featureCode("size"),
120 featureCode("ssty"), featureCode("stch"), featureCode("tjmo"), featureCode("vatu"),
121 featureCode("vert"), featureCode("vjmo"),
122 });
123 }
124
125 namespace
126 {
isCharacterVariantCode(sal_uInt32 nFeatureCode)127 bool isCharacterVariantCode(sal_uInt32 nFeatureCode)
128 {
129 return char((sal_uInt32(nFeatureCode) >> 24) & 0xFF) == 'c'
130 && char((sal_uInt32(nFeatureCode) >> 16) & 0xFF) == 'v';
131 }
132
isStylisticSetCode(sal_uInt32 nFeatureCode)133 bool isStylisticSetCode(sal_uInt32 nFeatureCode)
134 {
135 return char((sal_uInt32(nFeatureCode) >> 24) & 0xFF) == 's'
136 && char((sal_uInt32(nFeatureCode) >> 16) & 0xFF) == 's';
137 }
138
getNumericLowerPart(sal_uInt32 nFeatureCode)139 OUString getNumericLowerPart(sal_uInt32 nFeatureCode)
140 {
141 char cChar1((sal_uInt32(nFeatureCode) >> 8) & 0xFF);
142 char cChar2((sal_uInt32(nFeatureCode) >> 0) & 0xFF);
143
144 if (rtl::isAsciiDigit(static_cast<unsigned char>(cChar1))
145 && rtl::isAsciiDigit(static_cast<unsigned char>(cChar2)))
146 {
147 return OUStringChar(cChar1) + OUStringChar(cChar2);
148 }
149 return OUString();
150 }
151
152 } // end anonymous namespace
153
isSpecialFeatureCode(sal_uInt32 nFeatureCode)154 bool OpenTypeFeatureDefinitionListPrivate::isSpecialFeatureCode(sal_uInt32 nFeatureCode)
155 {
156 return isCharacterVariantCode(nFeatureCode) || isStylisticSetCode(nFeatureCode);
157 }
158
159 FeatureDefinition
handleSpecialFeatureCode(sal_uInt32 nFeatureCode)160 OpenTypeFeatureDefinitionListPrivate::handleSpecialFeatureCode(sal_uInt32 nFeatureCode)
161 {
162 FeatureDefinition aFeatureDefinition;
163 OUString sNumericPart = getNumericLowerPart(nFeatureCode);
164 if (!sNumericPart.isEmpty())
165 {
166 if (isCharacterVariantCode(nFeatureCode))
167 aFeatureDefinition = { nFeatureCode, STR_FONT_FEATURE_ID_CVXX, sNumericPart };
168 else if (isStylisticSetCode(nFeatureCode))
169 aFeatureDefinition = { nFeatureCode, STR_FONT_FEATURE_ID_SSXX, sNumericPart };
170 }
171 return aFeatureDefinition;
172 }
173
getDefinition(sal_uInt32 nFeatureCode)174 FeatureDefinition OpenTypeFeatureDefinitionListPrivate::getDefinition(sal_uInt32 nFeatureCode)
175 {
176 if (isSpecialFeatureCode(nFeatureCode))
177 {
178 return handleSpecialFeatureCode(nFeatureCode);
179 }
180
181 if (m_aCodeToIndex.find(nFeatureCode) != m_aCodeToIndex.end())
182 {
183 size_t nIndex = m_aCodeToIndex.at(nFeatureCode);
184 return m_aFeatureDefinition[nIndex];
185 }
186 return FeatureDefinition();
187 }
188
isRequired(sal_uInt32 nFeatureCode)189 bool OpenTypeFeatureDefinitionListPrivate::isRequired(sal_uInt32 nFeatureCode)
190 {
191 return std::find(m_aRequiredFeatures.begin(), m_aRequiredFeatures.end(), nFeatureCode)
192 != m_aRequiredFeatures.end();
193 }
194
195 } // end vcl::font namespace
196
197 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
198