1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
21 // Parse a string of features specified as & separated pairs.
23 // 1001=1&2002=2&fav1=0
26 #include <sal/types.h>
27 #include <osl/endian.h>
33 #include <graphite_features.hxx>
35 using namespace grutils
;
36 // These mustn't conflict with font name lists which use ; and ,
37 const char GrFeatureParser::FEAT_PREFIX
= ':';
38 const char GrFeatureParser::FEAT_SEPARATOR
= '&';
39 const char GrFeatureParser::FEAT_ID_VALUE_SEPARATOR
= '=';
41 GrFeatureParser::GrFeatureParser(const gr_face
* pFace
, const OString lang
)
42 : mnNumSettings(0), mbErrors(false), mpSettings(NULL
)
44 maLang
.label
[0] = maLang
.label
[1] = maLang
.label
[2] = maLang
.label
[3] = '\0';
48 GrFeatureParser::GrFeatureParser(const gr_face
* pFace
, const OString features
, const OString lang
)
49 : mnNumSettings(0), mbErrors(false), mpSettings(NULL
)
51 sal_Int32 nEquals
= 0;
52 sal_Int32 nFeatEnd
= 0;
56 while ((pos
< features
.getLength()) && (mnNumSettings
< MAX_FEATURES
))
58 nEquals
= features
.indexOf(FEAT_ID_VALUE_SEPARATOR
, pos
);
64 // check for a lang=xxx specification
65 const OString
aLangPrefix("lang");
66 if (features
.match(aLangPrefix
, pos
))
69 nFeatEnd
= features
.indexOf(FEAT_SEPARATOR
, pos
);
72 nFeatEnd
= features
.getLength();
74 if (nFeatEnd
- pos
> 3)
78 FeatId aLang
= maLang
;
80 for (sal_Int32 i
= pos
; i
< nFeatEnd
; i
++)
81 aLang
.label
[i
-pos
] = features
[i
];
83 //ext_std::pair<gr::LanguageIterator,gr::LanguageIterator> aSupported
84 // = font.getSupportedLanguages();
85 //gr::LanguageIterator iL = aSupported.first;
87 for (; i
< gr_face_n_languages(pFace
); i
++)
89 gr_uint32 nFaceLang
= gr_face_lang_by_index(pFace
, i
);
90 FeatId aSupportedLang
;
91 aSupportedLang
.num
= nFaceLang
;
93 // here we only expect full 3 letter codes
94 if (aLang
.label
[0] == aSupportedLang
.label
[0] &&
95 aLang
.label
[1] == aSupportedLang
.label
[1] &&
96 aLang
.label
[2] == aSupportedLang
.label
[2] &&
97 aLang
.label
[3] == aSupportedLang
.label
[3])
99 if (aLang
.label
[0] == aSupportedLang
.label
[3] &&
100 aLang
.label
[1] == aSupportedLang
.label
[2] &&
101 aLang
.label
[2] == aSupportedLang
.label
[1] &&
102 aLang
.label
[3] == aSupportedLang
.label
[0])
105 maLang
= aSupportedLang
;
109 if (i
== gr_face_n_languages(pFace
)) mbErrors
= true;
113 mpSettings
= gr_face_featureval_for_lang(pFace
, maLang
.num
);
119 sal_uInt32 featId
= 0;
120 if (isCharId(features
, pos
, nEquals
- pos
))
122 featId
= getCharId(features
, pos
, nEquals
- pos
);
126 featId
= getIntValue(features
, pos
, nEquals
- pos
);
128 const gr_feature_ref
* pFref
= gr_face_find_fref(pFace
, featId
);
130 nFeatEnd
= features
.indexOf(FEAT_SEPARATOR
, pos
);
133 nFeatEnd
= features
.getLength();
135 sal_Int16 featValue
= 0;
136 featValue
= getIntValue(features
, pos
, nFeatEnd
- pos
);
137 if (pFref
&& gr_fref_set_feature_value(pFref
, featValue
, mpSettings
))
139 mnHash
= (mnHash
<< 16) ^ ((featId
<< 8) | featValue
);
149 void GrFeatureParser::setLang(const gr_face
* pFace
, const OString
& lang
)
153 if (lang
.getLength() >= 2)
155 for (sal_Int32 i
= 0; i
< lang
.getLength() && i
< 3; i
++)
157 if (lang
[i
] == '-') break;
158 aLang
.label
[i
] = lang
[i
];
160 unsigned short i
= 0;
161 for (; i
< gr_face_n_languages(pFace
); i
++)
163 gr_uint32 nFaceLang
= gr_face_lang_by_index(pFace
, i
);
164 FeatId aSupportedLang
;
165 aSupportedLang
.num
= nFaceLang
;
166 // here we only expect full 2 & 3 letter codes
168 if (aLang
.label
[0] == aSupportedLang
.label
[0] &&
169 aLang
.label
[1] == aSupportedLang
.label
[1] &&
170 aLang
.label
[2] == aSupportedLang
.label
[2] &&
171 aLang
.label
[3] == aSupportedLang
.label
[3])
173 if (aLang
.label
[0] == aSupportedLang
.label
[3] &&
174 aLang
.label
[1] == aSupportedLang
.label
[2] &&
175 aLang
.label
[2] == aSupportedLang
.label
[1] &&
176 aLang
.label
[3] == aSupportedLang
.label
[0])
179 maLang
= aSupportedLang
;
183 if (i
!= gr_face_n_languages(pFace
))
186 gr_featureval_destroy(mpSettings
);
187 mpSettings
= gr_face_featureval_for_lang(pFace
, maLang
.num
);
192 mpSettings
= gr_face_featureval_for_lang(pFace
, 0);
195 GrFeatureParser::~GrFeatureParser()
199 gr_featureval_destroy(mpSettings
);
204 bool GrFeatureParser::isCharId(const OString
& id
, size_t offset
, size_t length
)
206 if (length
> 4) return false;
207 for (size_t i
= 0; i
< length
; i
++)
209 if (i
> 0 && id
[offset
+i
] == '\0') continue;
210 if ((id
[offset
+i
] < 0x20) || (id
[offset
+i
] < 0))
212 if (i
==0 && (id
[offset
+i
] < 0x41))
218 gr_uint32
GrFeatureParser::getCharId(const OString
& id
, size_t offset
, size_t length
)
223 for (size_t i
= 0; i
< length
; i
++)
225 charId
.label
[i
] = id
[offset
+i
];
228 for (size_t i
= 0; i
< length
; i
++)
230 charId
.label
[3-i
] = id
[offset
+i
];
236 short GrFeatureParser::getIntValue(const OString
& id
, size_t offset
, size_t length
)
240 for (size_t i
= 0; i
< length
; i
++)
242 switch (id
[offset
+ i
])
257 value
= -(id
[offset
+ i
] - '0');
260 value
+= (id
[offset
+ i
] - '0');
278 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */