merge the formfield patch from ooo-build
[ooovba.git] / vcl / source / glyphs / graphite_features.cxx
blob48d3ad9842b9ee92efff91b4928ebd1c5ad02e9b
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: $
10 * $Revision: $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // Description:
32 // Parse a string of features specified as & separated pairs.
33 // e.g.
34 // 1001=1&2002=2&fav1=0
36 // MARKER(update_precomp.py): autogen include statement, do not remove
37 #include "precompiled_vcl.hxx"
39 #include <sal/types.h>
41 #ifdef WNT
42 #include <tools/svwin.h>
43 #include <svsys.h>
44 #endif
46 #include <vcl/graphite_features.hxx>
48 using namespace grutils;
49 // These mustn't conflict with font name lists which use ; and ,
50 const char GrFeatureParser::FEAT_PREFIX = ':';
51 const char GrFeatureParser::FEAT_SEPARATOR = '&';
52 const char GrFeatureParser::FEAT_ID_VALUE_SEPARATOR = '=';
53 const std::string GrFeatureParser::ISO_LANG("lang");
55 GrFeatureParser::GrFeatureParser(gr::Font & font, const std::string lang)
56 : mnNumSettings(0), mbErrors(false)
58 maLang.rgch[0] = maLang.rgch[1] = maLang.rgch[2] = maLang.rgch[3] = '\0';
59 setLang(font, lang);
62 GrFeatureParser::GrFeatureParser(gr::Font & font, const std::string features, const std::string lang)
63 : mnNumSettings(0), mbErrors(false)
65 size_t nEquals = 0;
66 size_t nFeatEnd = 0;
67 size_t pos = 0;
68 maLang.rgch[0] = maLang.rgch[1] = maLang.rgch[2] = maLang.rgch[3] = '\0';
69 setLang(font, lang);
70 while (pos < features.length() && mnNumSettings < MAX_FEATURES)
72 nEquals = features.find(FEAT_ID_VALUE_SEPARATOR,pos);
73 if (nEquals == std::string::npos)
75 mbErrors = true;
76 break;
78 // check for a lang=xxx specification
79 if (features.compare(pos, nEquals - pos, ISO_LANG) == 0)
81 pos = nEquals + 1;
82 nFeatEnd = features.find(FEAT_SEPARATOR, pos);
83 if (nFeatEnd == std::string::npos)
85 nFeatEnd = features.length();
87 if (nFeatEnd - pos > 3)
88 mbErrors = true;
89 else
91 gr::isocode aLang = maLang;
92 for (size_t i = pos; i < nFeatEnd; i++)
93 aLang.rgch[i-pos] = features[i];
94 std::pair<gr::LanguageIterator,gr::LanguageIterator> aSupported
95 = font.getSupportedLanguages();
96 gr::LanguageIterator iL = aSupported.first;
97 while (iL != aSupported.second)
99 gr::isocode aSupportedLang = *iL;
100 // here we only expect full 3 letter codes
101 if (aLang.rgch[0] == aSupportedLang.rgch[0] &&
102 aLang.rgch[1] == aSupportedLang.rgch[1] &&
103 aLang.rgch[2] == aSupportedLang.rgch[2] &&
104 aLang.rgch[3] == aSupportedLang.rgch[3]) break;
105 ++iL;
107 if (iL == aSupported.second) mbErrors = true;
108 else maLang = aLang;
111 else
113 if (isCharId(features, pos, nEquals - pos))
114 maSettings[mnNumSettings].id = getCharId(features, pos, nEquals - pos);
115 else maSettings[mnNumSettings].id = getIntValue(features, pos, nEquals - pos);
116 pos = nEquals + 1;
117 nFeatEnd = features.find(FEAT_SEPARATOR, pos);
118 if (nFeatEnd == std::string::npos)
120 nFeatEnd = features.length();
122 if (isCharId(features, pos, nFeatEnd - pos))
123 maSettings[mnNumSettings].value = getCharId(features, pos, nFeatEnd - pos);
124 else
125 maSettings[mnNumSettings].value= getIntValue(features, pos, nFeatEnd - pos);
126 if (isValid(font, maSettings[mnNumSettings]))
127 mnNumSettings++;
128 else
129 mbErrors = true;
131 pos = nFeatEnd + 1;
135 void GrFeatureParser::setLang(gr::Font & font, const std::string & lang)
137 gr::isocode aLang = {{0,0,0,0}};
138 if (lang.length() > 2)
140 for (size_t i = 0; i < lang.length() && i < 3; i++)
142 if (lang[i] == '-') break;
143 aLang.rgch[i] = lang[i];
145 std::pair<gr::LanguageIterator,gr::LanguageIterator> aSupported
146 = font.getSupportedLanguages();
147 gr::LanguageIterator iL = aSupported.first;
148 while (iL != aSupported.second)
150 gr::isocode aSupportedLang = *iL;
151 if (aLang.rgch[0] == aSupportedLang.rgch[0] &&
152 aLang.rgch[1] == aSupportedLang.rgch[1] &&
153 aLang.rgch[2] == aSupportedLang.rgch[2] &&
154 aLang.rgch[3] == aSupportedLang.rgch[3]) break;
155 ++iL;
157 if (iL != aSupported.second)
158 maLang = aLang;
159 #ifdef DEBUG
160 else
161 printf("%s has no features\n", aLang.rgch);
162 #endif
166 GrFeatureParser::GrFeatureParser(const GrFeatureParser & aCopy)
167 : maLang(aCopy.maLang), mbErrors(aCopy.mbErrors)
169 mnNumSettings = aCopy.getFontFeatures(maSettings);
172 GrFeatureParser::~GrFeatureParser()
176 size_t GrFeatureParser::getFontFeatures(gr::FeatureSetting settings[64]) const
178 if (settings)
180 std::copy(maSettings, maSettings + mnNumSettings, settings);
182 return mnNumSettings;
185 bool GrFeatureParser::isValid(gr::Font & font, gr::FeatureSetting & setting)
187 gr::FeatureIterator i = font.featureWithID(setting.id);
188 if (font.getFeatures().second == i)
190 return false;
192 std::pair< gr::FeatureSettingIterator, gr::FeatureSettingIterator >
193 validValues = font.getFeatureSettings(i);
194 gr::FeatureSettingIterator j = validValues.first;
195 while (j != validValues.second)
197 if (*j == setting.value) return true;
198 ++j;
200 return false;
203 bool GrFeatureParser::isCharId(const std::string & 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 || (id[offset+i]) < 0)
210 return false;
211 if (i==0 && id[offset+i] < 0x41)
212 return false;
214 return true;
217 int GrFeatureParser::getCharId(const std::string & id, size_t offset, size_t length)
219 FeatId charId;
220 charId.num = 0;
221 #ifdef WORDS_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 int GrFeatureParser::getIntValue(const std::string & id, size_t offset, size_t length)
237 int 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;
278 sal_Int32 GrFeatureParser::hashCode() const
280 union IsoHash { sal_Int32 mInt; gr::isocode mCode; };
281 IsoHash isoHash;
282 isoHash.mCode = maLang;
283 sal_Int32 hash = isoHash.mInt;
284 for (size_t i = 0; i < mnNumSettings; i++)
286 hash = (hash << 16) ^ ((maSettings[i].id << 8) | maSettings[i].value);
288 return hash;