Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : // Description:
30 : : // Parse a string of features specified as & separated pairs.
31 : : // e.g.
32 : : // 1001=1&2002=2&fav1=0
33 : :
34 : :
35 : : #include <sal/types.h>
36 : :
37 : : #ifdef WNT
38 : : #include <windows.h>
39 : : #endif
40 : :
41 : : #include <graphite_features.hxx>
42 : :
43 : : using namespace grutils;
44 : : // These mustn't conflict with font name lists which use ; and ,
45 : : const char GrFeatureParser::FEAT_PREFIX = ':';
46 : : const char GrFeatureParser::FEAT_SEPARATOR = '&';
47 : : const char GrFeatureParser::FEAT_ID_VALUE_SEPARATOR = '=';
48 : :
49 : 0 : GrFeatureParser::GrFeatureParser(const gr_face * pFace, const ::rtl::OString lang)
50 : 0 : : mnNumSettings(0), mbErrors(false), mpSettings(NULL)
51 : : {
52 : 0 : maLang.label[0] = maLang.label[1] = maLang.label[2] = maLang.label[3] = '\0';
53 : 0 : setLang(pFace, lang);
54 : 0 : }
55 : :
56 : 0 : GrFeatureParser::GrFeatureParser(const gr_face * pFace, const ::rtl::OString features, const ::rtl::OString lang)
57 : 0 : : mnNumSettings(0), mbErrors(false), mpSettings(NULL)
58 : : {
59 : 0 : sal_Int32 nEquals = 0;
60 : 0 : sal_Int32 nFeatEnd = 0;
61 : 0 : sal_Int32 pos = 0;
62 : 0 : maLang.num = 0u;
63 : 0 : setLang(pFace, lang);
64 [ # # ][ # # ]: 0 : while ((pos < features.getLength()) && (mnNumSettings < MAX_FEATURES))
[ # # ]
65 : : {
66 : 0 : nEquals = features.indexOf(FEAT_ID_VALUE_SEPARATOR, pos);
67 [ # # ]: 0 : if (nEquals == -1)
68 : : {
69 : 0 : mbErrors = true;
70 : : break;
71 : : }
72 : : // check for a lang=xxx specification
73 : 0 : const ::rtl::OString aLangPrefix("lang");
74 [ # # ]: 0 : if (features.match(aLangPrefix, pos ))
75 : : {
76 : 0 : pos = nEquals + 1;
77 : 0 : nFeatEnd = features.indexOf(FEAT_SEPARATOR, pos);
78 [ # # ]: 0 : if (nFeatEnd == -1)
79 : : {
80 : 0 : nFeatEnd = features.getLength();
81 : : }
82 [ # # ]: 0 : if (nFeatEnd - pos > 3)
83 : 0 : mbErrors = true;
84 : : else
85 : : {
86 : 0 : FeatId aLang = maLang;
87 : 0 : aLang.num = 0;
88 [ # # ]: 0 : for (sal_Int32 i = pos; i < nFeatEnd; i++)
89 : 0 : aLang.label[i-pos] = features[i];
90 : :
91 : : //ext_std::pair<gr::LanguageIterator,gr::LanguageIterator> aSupported
92 : : // = font.getSupportedLanguages();
93 : : //gr::LanguageIterator iL = aSupported.first;
94 : 0 : unsigned short i = 0;
95 [ # # ][ # # ]: 0 : for (; i < gr_face_n_languages(pFace); i++)
96 : : {
97 [ # # ]: 0 : gr_uint32 nFaceLang = gr_face_lang_by_index(pFace, i);
98 : : FeatId aSupportedLang;
99 : 0 : aSupportedLang.num = nFaceLang;
100 : : #ifdef __BIG_ENDIAN__
101 : : // here we only expect full 3 letter codes
102 : : if (aLang.label[0] == aSupportedLang.label[0] &&
103 : : aLang.label[1] == aSupportedLang.label[1] &&
104 : : aLang.label[2] == aSupportedLang.label[2] &&
105 : : aLang.label[3] == aSupportedLang.label[3])
106 : : #else
107 [ # # ][ # # ]: 0 : if (aLang.label[0] == aSupportedLang.label[3] &&
[ # # ][ # # ]
108 : 0 : aLang.label[1] == aSupportedLang.label[2] &&
109 : 0 : aLang.label[2] == aSupportedLang.label[1] &&
110 : 0 : aLang.label[3] == aSupportedLang.label[0])
111 : : #endif
112 : : {
113 : 0 : maLang = aSupportedLang;
114 : : break;
115 : : }
116 : : }
117 [ # # ][ # # ]: 0 : if (i == gr_face_n_languages(pFace)) mbErrors = true;
118 : : else
119 : : {
120 : 0 : mnHash = maLang.num;
121 [ # # ]: 0 : mpSettings = gr_face_featureval_for_lang(pFace, maLang.num);
122 : : }
123 : : }
124 : : }
125 : : else
126 : : {
127 : 0 : sal_uInt32 featId = 0;
128 [ # # ]: 0 : if (isCharId(features, pos, nEquals - pos))
129 : : {
130 : 0 : featId = getCharId(features, pos, nEquals - pos);
131 : : }
132 : : else
133 : : {
134 : 0 : featId = getIntValue(features, pos, nEquals - pos);
135 : : }
136 [ # # ]: 0 : const gr_feature_ref * pFref = gr_face_find_fref(pFace, featId);
137 : 0 : pos = nEquals + 1;
138 : 0 : nFeatEnd = features.indexOf(FEAT_SEPARATOR, pos);
139 [ # # ]: 0 : if (nFeatEnd == -1)
140 : : {
141 : 0 : nFeatEnd = features.getLength();
142 : : }
143 : 0 : sal_Int16 featValue = 0;
144 : 0 : featValue = getIntValue(features, pos, nFeatEnd - pos);
145 [ # # ][ # # ]: 0 : if (pFref && gr_fref_set_feature_value(pFref, featValue, mpSettings))
[ # # ][ # # ]
146 : : {
147 : 0 : mnHash = (mnHash << 16) ^ ((featId << 8) | featValue);
148 : 0 : mnNumSettings++;
149 : : }
150 : : else
151 : 0 : mbErrors = true;
152 : : }
153 : 0 : pos = nFeatEnd + 1;
154 : 0 : }
155 : 0 : }
156 : :
157 : 0 : void GrFeatureParser::setLang(const gr_face * pFace, const rtl::OString & lang)
158 : : {
159 : : FeatId aLang;
160 : 0 : aLang.num = 0;
161 [ # # ]: 0 : if (lang.getLength() >= 2)
162 : : {
163 [ # # ][ # # ]: 0 : for (sal_Int32 i = 0; i < lang.getLength() && i < 3; i++)
[ # # ]
164 : : {
165 [ # # ]: 0 : if (lang[i] == '-') break;
166 : 0 : aLang.label[i] = lang[i];
167 : : }
168 : 0 : unsigned short i = 0;
169 [ # # ][ # # ]: 0 : for (; i < gr_face_n_languages(pFace); i++)
170 : : {
171 [ # # ]: 0 : gr_uint32 nFaceLang = gr_face_lang_by_index(pFace, i);
172 : : FeatId aSupportedLang;
173 : 0 : aSupportedLang.num = nFaceLang;
174 : : // here we only expect full 2 & 3 letter codes
175 : : #ifdef __BIG_ENDIAN__
176 : : if (aLang.label[0] == aSupportedLang.label[0] &&
177 : : aLang.label[1] == aSupportedLang.label[1] &&
178 : : aLang.label[2] == aSupportedLang.label[2] &&
179 : : aLang.label[3] == aSupportedLang.label[3])
180 : : #else
181 [ # # ][ # # ]: 0 : if (aLang.label[0] == aSupportedLang.label[3] &&
[ # # ][ # # ]
182 : 0 : aLang.label[1] == aSupportedLang.label[2] &&
183 : 0 : aLang.label[2] == aSupportedLang.label[1] &&
184 : 0 : aLang.label[3] == aSupportedLang.label[0])
185 : : #endif
186 : : {
187 : 0 : maLang = aSupportedLang;
188 : : break;
189 : : }
190 : : }
191 [ # # ][ # # ]: 0 : if (i != gr_face_n_languages(pFace))
192 : : {
193 [ # # ]: 0 : if (mpSettings)
194 [ # # ]: 0 : gr_featureval_destroy(mpSettings);
195 [ # # ]: 0 : mpSettings = gr_face_featureval_for_lang(pFace, maLang.num);
196 : 0 : mnHash = maLang.num;
197 : : }
198 : : }
199 [ # # ]: 0 : if (!mpSettings)
200 [ # # ]: 0 : mpSettings = gr_face_featureval_for_lang(pFace, 0);
201 : 0 : }
202 : :
203 : 0 : GrFeatureParser::~GrFeatureParser()
204 : : {
205 [ # # ]: 0 : if (mpSettings)
206 : : {
207 : 0 : gr_featureval_destroy(mpSettings);
208 : 0 : mpSettings = NULL;
209 : : }
210 : 0 : }
211 : :
212 : 0 : bool GrFeatureParser::isCharId(const rtl::OString & id, size_t offset, size_t length)
213 : : {
214 [ # # ]: 0 : if (length > 4) return false;
215 [ # # ]: 0 : for (size_t i = 0; i < length; i++)
216 : : {
217 [ # # ][ # # ]: 0 : if (i > 0 && id[offset+i] == '\0') continue;
[ # # ]
218 [ # # ][ # # ]: 0 : if ((id[offset+i] < 0x20) || (id[offset+i] < 0))
[ # # ]
219 : 0 : return false;
220 [ # # ][ # # ]: 0 : if (i==0 && (id[offset+i] < 0x41))
[ # # ]
221 : 0 : return false;
222 : : }
223 : 0 : return true;
224 : : }
225 : :
226 : 0 : gr_uint32 GrFeatureParser::getCharId(const rtl::OString & id, size_t offset, size_t length)
227 : : {
228 : : FeatId charId;
229 : 0 : charId.num = 0;
230 : : #ifdef WORDS_BIGENDIAN
231 : : for (size_t i = 0; i < length; i++)
232 : : {
233 : : charId.label[i] = id[offset+i];
234 : : }
235 : : #else
236 [ # # ]: 0 : for (size_t i = 0; i < length; i++)
237 : : {
238 : 0 : charId.label[3-i] = id[offset+i];
239 : : }
240 : : #endif
241 : 0 : return charId.num;
242 : : }
243 : :
244 : 0 : short GrFeatureParser::getIntValue(const rtl::OString & id, size_t offset, size_t length)
245 : : {
246 : 0 : short value = 0;
247 : 0 : int sign = 1;
248 [ # # ]: 0 : for (size_t i = 0; i < length; i++)
249 : : {
250 [ # # # ]: 0 : switch (id[offset + i])
251 : : {
252 : : case '0':
253 : : case '1':
254 : : case '2':
255 : : case '3':
256 : : case '4':
257 : : case '5':
258 : : case '6':
259 : : case '7':
260 : : case '8':
261 : : case '9':
262 : 0 : value *= 10;
263 [ # # ]: 0 : if (sign < 0)
264 : : {
265 : 0 : value = -(id[offset + i] - '0');
266 : 0 : sign = 1;
267 : : }
268 : 0 : value += (id[offset + i] - '0');
269 : 0 : break;
270 : : case '-':
271 [ # # ]: 0 : if (i == 0)
272 : 0 : sign = -1;
273 : : else
274 : : {
275 : 0 : mbErrors = true;
276 : 0 : break;
277 : : }
278 : : default:
279 : 0 : mbErrors = true;
280 : 0 : break;
281 : : }
282 : : }
283 : 0 : return value;
284 : : }
285 : :
286 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|