Branch libreoffice-5-0-4
[LibreOffice.git] / vcl / source / glyphs / graphite_features.cxx
blob83a240508e463d3d6a19bbd98ce51a6db24edf43
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 // Description:
21 // Parse a string of features specified as & separated pairs.
22 // e.g.
23 // 1001=1&2002=2&fav1=0
25 #include <sal/types.h>
26 #include <osl/endian.h>
28 #ifdef WNT
29 #include <windows.h>
30 #endif
32 #include <graphite_features.hxx>
34 using namespace grutils;
35 // These mustn't conflict with font name lists which use ; and ,
36 const char GrFeatureParser::FEAT_PREFIX = ':';
37 const char GrFeatureParser::FEAT_SEPARATOR = '&';
38 const char GrFeatureParser::FEAT_ID_VALUE_SEPARATOR = '=';
40 GrFeatureParser::GrFeatureParser(const gr_face * pFace, const OString& lang)
41 : mnNumSettings(0), mbErrors(false), mpSettings(NULL)
43 maLang.label[0] = maLang.label[1] = maLang.label[2] = maLang.label[3] = '\0';
44 setLang(pFace, lang);
47 GrFeatureParser::GrFeatureParser(const gr_face * pFace, const OString& features, const OString& lang)
48 : mnNumSettings(0), mbErrors(false), mpSettings(NULL)
50 sal_Int32 nEquals = 0;
51 sal_Int32 nFeatEnd = 0;
52 sal_Int32 pos = 0;
53 maLang.num = 0u;
54 setLang(pFace, lang);
55 while ((pos < features.getLength()) && (mnNumSettings < MAX_FEATURES))
57 nEquals = features.indexOf(FEAT_ID_VALUE_SEPARATOR, pos);
58 if (nEquals == -1)
60 mbErrors = true;
61 break;
63 // check for a lang=xxx specification
64 const OString aLangPrefix("lang");
65 if (features.match(aLangPrefix, pos ))
67 pos = nEquals + 1;
68 nFeatEnd = features.indexOf(FEAT_SEPARATOR, pos);
69 if (nFeatEnd == -1)
71 nFeatEnd = features.getLength();
73 if (nFeatEnd - pos > 3)
74 mbErrors = true;
75 else
77 FeatId aLang = maLang;
78 aLang.num = 0;
79 for (sal_Int32 i = pos; i < nFeatEnd; i++)
80 aLang.label[i-pos] = features[i];
82 //ext_std::pair<gr::LanguageIterator,gr::LanguageIterator> aSupported
83 // = font.getSupportedLanguages();
84 //gr::LanguageIterator iL = aSupported.first;
85 unsigned short i = 0;
86 for (; i < gr_face_n_languages(pFace); i++)
88 gr_uint32 nFaceLang = gr_face_lang_by_index(pFace, i);
89 FeatId aSupportedLang;
90 aSupportedLang.num = nFaceLang;
91 #ifdef OSL_BIGENDIAN
92 // here we only expect full 3 letter codes
93 if (aLang.label[0] == aSupportedLang.label[0] &&
94 aLang.label[1] == aSupportedLang.label[1] &&
95 aLang.label[2] == aSupportedLang.label[2] &&
96 aLang.label[3] == aSupportedLang.label[3])
97 #else
98 if (aLang.label[0] == aSupportedLang.label[3] &&
99 aLang.label[1] == aSupportedLang.label[2] &&
100 aLang.label[2] == aSupportedLang.label[1] &&
101 aLang.label[3] == aSupportedLang.label[0])
102 #endif
104 maLang = aSupportedLang;
105 break;
108 if (i == gr_face_n_languages(pFace)) mbErrors = true;
109 else
111 mnHash = maLang.num;
112 mpSettings = gr_face_featureval_for_lang(pFace, maLang.num);
116 else
118 sal_uInt32 featId = 0;
119 if (isCharId(features, pos, nEquals - pos))
121 featId = getCharId(features, pos, nEquals - pos);
123 else
125 featId = getIntValue(features, pos, nEquals - pos);
127 const gr_feature_ref * pFref = gr_face_find_fref(pFace, featId);
128 pos = nEquals + 1;
129 nFeatEnd = features.indexOf(FEAT_SEPARATOR, pos);
130 if (nFeatEnd == -1)
132 nFeatEnd = features.getLength();
134 sal_Int16 featValue = 0;
135 featValue = getIntValue(features, pos, nFeatEnd - pos);
136 if (pFref && gr_fref_set_feature_value(pFref, featValue, mpSettings))
138 mnHash = (mnHash << 16) ^ ((featId << 8) | featValue);
139 mnNumSettings++;
141 else
142 mbErrors = true;
144 pos = nFeatEnd + 1;
148 void GrFeatureParser::setLang(const gr_face * pFace, const OString & lang)
150 FeatId aLang;
151 aLang.num = 0;
152 if (lang.getLength() >= 2)
154 for (sal_Int32 i = 0; i < lang.getLength() && i < 3; i++)
156 if (lang[i] == '-') break;
157 aLang.label[i] = lang[i];
159 unsigned short i = 0;
160 for (; i < gr_face_n_languages(pFace); i++)
162 gr_uint32 nFaceLang = gr_face_lang_by_index(pFace, i);
163 FeatId aSupportedLang;
164 aSupportedLang.num = nFaceLang;
165 // here we only expect full 2 & 3 letter codes
166 #ifdef OSL_BIGENDIAN
167 if (aLang.label[0] == aSupportedLang.label[0] &&
168 aLang.label[1] == aSupportedLang.label[1] &&
169 aLang.label[2] == aSupportedLang.label[2] &&
170 aLang.label[3] == aSupportedLang.label[3])
171 #else
172 if (aLang.label[0] == aSupportedLang.label[3] &&
173 aLang.label[1] == aSupportedLang.label[2] &&
174 aLang.label[2] == aSupportedLang.label[1] &&
175 aLang.label[3] == aSupportedLang.label[0])
176 #endif
178 maLang = aSupportedLang;
179 break;
182 if (i != gr_face_n_languages(pFace))
184 if (mpSettings)
185 gr_featureval_destroy(mpSettings);
186 mpSettings = gr_face_featureval_for_lang(pFace, maLang.num);
187 mnHash = maLang.num;
190 if (!mpSettings)
191 mpSettings = gr_face_featureval_for_lang(pFace, 0);
194 GrFeatureParser::~GrFeatureParser()
196 if (mpSettings)
198 gr_featureval_destroy(mpSettings);
199 mpSettings = NULL;
203 bool GrFeatureParser::isCharId(const OString & id, size_t offset, size_t length)
205 if (length > 4) return false;
206 for (size_t i = 0; i < length; i++)
208 if (i > 0 && id[offset+i] == '\0') continue;
209 if (id[offset+i] < 0x20 || static_cast<signed char>(id[offset+i]) < 0)
210 return false;
211 if (i==0 && (id[offset+i] < 0x41))
212 return false;
214 return true;
217 gr_uint32 GrFeatureParser::getCharId(const OString & id, size_t offset, size_t length)
219 FeatId charId;
220 charId.num = 0;
221 #ifdef OSL_BIGENDIAN
222 for (size_t i = 0; i < length; i++)
224 charId.label[i] = id[offset+i];
226 #else
227 for (size_t i = 0; i < length; i++)
229 charId.label[3-i] = id[offset+i];
231 #endif
232 return charId.num;
235 short GrFeatureParser::getIntValue(const OString & id, size_t offset, size_t length)
237 short value = 0;
238 int sign = 1;
239 for (size_t i = 0; i < length; i++)
241 switch (id[offset + i])
243 case '0':
244 case '1':
245 case '2':
246 case '3':
247 case '4':
248 case '5':
249 case '6':
250 case '7':
251 case '8':
252 case '9':
253 value *= 10;
254 if (sign < 0)
256 value = -(id[offset + i] - '0');
257 sign = 1;
259 value += (id[offset + i] - '0');
260 break;
261 case '-':
262 if (i == 0)
263 sign = -1;
264 else
266 mbErrors = true;
267 break;
269 default:
270 mbErrors = true;
271 break;
274 return value;
277 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */