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
25 #include <sal/types.h>
26 #include <osl/endian.h>
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';
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;
55 while ((pos
< features
.getLength()) && (mnNumSettings
< MAX_FEATURES
))
57 nEquals
= features
.indexOf(FEAT_ID_VALUE_SEPARATOR
, pos
);
63 // check for a lang=xxx specification
64 const OString
aLangPrefix("lang");
65 if (features
.match(aLangPrefix
, pos
))
68 nFeatEnd
= features
.indexOf(FEAT_SEPARATOR
, pos
);
71 nFeatEnd
= features
.getLength();
73 if (nFeatEnd
- pos
> 3)
77 FeatId aLang
= maLang
;
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;
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
;
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])
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])
104 maLang
= aSupportedLang
;
108 if (i
== gr_face_n_languages(pFace
)) mbErrors
= true;
112 mpSettings
= gr_face_featureval_for_lang(pFace
, maLang
.num
);
118 sal_uInt32 featId
= 0;
119 if (isCharId(features
, pos
, nEquals
- pos
))
121 featId
= getCharId(features
, pos
, nEquals
- pos
);
125 featId
= getIntValue(features
, pos
, nEquals
- pos
);
127 const gr_feature_ref
* pFref
= gr_face_find_fref(pFace
, featId
);
129 nFeatEnd
= features
.indexOf(FEAT_SEPARATOR
, pos
);
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
);
148 void GrFeatureParser::setLang(const gr_face
* pFace
, const OString
& lang
)
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
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])
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])
178 maLang
= aSupportedLang
;
182 if (i
!= gr_face_n_languages(pFace
))
185 gr_featureval_destroy(mpSettings
);
186 mpSettings
= gr_face_featureval_for_lang(pFace
, maLang
.num
);
191 mpSettings
= gr_face_featureval_for_lang(pFace
, 0);
194 GrFeatureParser::~GrFeatureParser()
198 gr_featureval_destroy(mpSettings
);
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)
211 if (i
==0 && (id
[offset
+i
] < 0x41))
217 gr_uint32
GrFeatureParser::getCharId(const OString
& id
, size_t offset
, size_t length
)
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 short GrFeatureParser::getIntValue(const OString
& 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');
277 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */