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
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 ************************************************************************/
32 // Parse a string of features specified as & separated pairs.
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>
42 #include <tools/svwin.h>
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';
62 GrFeatureParser::GrFeatureParser(gr::Font
& font
, const std::string features
, const std::string lang
)
63 : mnNumSettings(0), mbErrors(false)
68 maLang
.rgch
[0] = maLang
.rgch
[1] = maLang
.rgch
[2] = maLang
.rgch
[3] = '\0';
70 while (pos
< features
.length() && mnNumSettings
< MAX_FEATURES
)
72 nEquals
= features
.find(FEAT_ID_VALUE_SEPARATOR
,pos
);
73 if (nEquals
== std::string::npos
)
78 // check for a lang=xxx specification
79 if (features
.compare(pos
, nEquals
- pos
, ISO_LANG
) == 0)
82 nFeatEnd
= features
.find(FEAT_SEPARATOR
, pos
);
83 if (nFeatEnd
== std::string::npos
)
85 nFeatEnd
= features
.length();
87 if (nFeatEnd
- pos
> 3)
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;
107 if (iL
== aSupported
.second
) mbErrors
= true;
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
);
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
);
125 maSettings
[mnNumSettings
].value
= getIntValue(features
, pos
, nFeatEnd
- pos
);
126 if (isValid(font
, maSettings
[mnNumSettings
]))
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;
157 if (iL
!= aSupported
.second
)
161 printf("%s has no features\n", aLang
.rgch
);
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
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
)
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;
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)
211 if (i
==0 && id
[offset
+i
] < 0x41)
217 int GrFeatureParser::getCharId(const std::string
& id
, size_t offset
, size_t length
)
221 #ifdef WORDS_BIGENDIAN
222 for (size_t i
= 0; i
< length
; i
++)
224 charId
.label
[i
] = id
[offset
+i
];
227 for (size_t i
= 0; i
< length
; i
++)
229 charId
.label
[3-i
] = id
[offset
+i
];
235 int GrFeatureParser::getIntValue(const std::string
& id
, size_t offset
, size_t length
)
239 for (size_t i
= 0; i
< length
; i
++)
241 switch (id
[offset
+ i
])
256 value
= -(id
[offset
+ i
] - '0');
259 value
+= (id
[offset
+ i
] - '0');
278 sal_Int32
GrFeatureParser::hashCode() const
280 union IsoHash
{ sal_Int32 mInt
; gr::isocode mCode
; };
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
);