2 * \file ExternalTransforms.C
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Angus Leeming
8 * Full author contact details are available in file CREDITS.
13 #include "ExternalTransforms.h"
17 #include "support/lstrings.h"
18 #include "support/lyxlib.h" // float_equal
19 #include "support/tostr.h"
20 #include "support/translator.h"
22 #include <boost/regex.hpp>
24 #include <cmath> // std::abs
27 using lyx::support::float_equal;
28 using lyx::support::strToDbl;
36 string const ExtraData::get(string const & id) const
38 std::map<string, string>::const_iterator it = data_.find(id);
39 return it == data_.end() ? string() : it->second;
43 void ExtraData::set(string const & id, string const & data)
49 bool ResizeData::no_resize() const
51 return !usingScale() && width.zero() && height.zero();
55 bool ResizeData::usingScale() const
57 return (!scale.empty() && !float_equal(strToDbl(scale), 0.0, 0.05));
61 bool RotationData::no_rotation() const
63 return (angle.empty() || std::abs(strToDbl(angle)) < 0.1);
67 string const RotationData::adjAngle() const
69 // Ensure that angle lies in the range -360 < angle < 360
70 double rotAngle = strToDbl(angle);
71 if (std::abs(rotAngle) > 360.0) {
72 rotAngle -= 360.0 * floor(rotAngle / 360.0);
73 return tostr(rotAngle);
81 typedef Translator<RotationData::OriginType, string> OriginTranslator;
82 OriginTranslator const & originTranslator();
87 void RotationData::origin(string const & o)
89 origin_ = originTranslator().find(o);
93 string const RotationData::originString() const
95 return originTranslator().find(origin_);
99 string const ResizeLatexCommand::front_impl() const
101 if (data.no_resize())
104 std::ostringstream os;
105 if (data.usingScale()) {
106 double const scl = strToDbl(data.scale) / 100.0;
107 os << "\\scalebox{" << scl << "}[" << scl << "]{";
111 if (data.keepAspectRatio) {
112 if (data.width.inPixels(10) > data.height.inPixels(10))
113 width = data.width.asLatexString();
115 height = data.height.asLatexString();
117 if (!data.width.zero())
118 width = data.width.asLatexString();
119 if (!data.height.zero())
120 height = data.height.asLatexString();
131 string const ResizeLatexCommand::back_impl() const
133 if (data.no_resize())
142 std::ostream & operator<<(std::ostream & os, RotationData::OriginType type)
145 case RotationData::DEFAULT:
146 case RotationData::CENTER:
148 case RotationData::TOPLEFT:
149 case RotationData::TOPCENTER:
150 case RotationData::TOPRIGHT:
153 case RotationData::BOTTOMLEFT:
154 case RotationData::BOTTOMCENTER:
155 case RotationData::BOTTOMRIGHT:
158 case RotationData::BASELINELEFT:
159 case RotationData::BASELINECENTER:
160 case RotationData::BASELINERIGHT:
166 case RotationData::DEFAULT:
168 case RotationData::TOPLEFT:
169 case RotationData::BOTTOMLEFT:
170 case RotationData::BASELINELEFT:
173 case RotationData::CENTER:
174 case RotationData::TOPCENTER:
175 case RotationData::BOTTOMCENTER:
176 case RotationData::BASELINECENTER:
179 case RotationData::TOPRIGHT:
180 case RotationData::BOTTOMRIGHT:
181 case RotationData::BASELINERIGHT:
192 string const RotationLatexCommand::front_impl() const
194 if (data.no_rotation())
197 std::ostringstream os;
200 if (data.origin() != RotationData::DEFAULT)
201 os << "[origin=" << data.origin() << ']';
203 os << '{' << data.angle << "}{";
208 string const RotationLatexCommand::back_impl() const
210 if (data.no_rotation())
217 string const ClipLatexOption::option_impl() const
219 if (!data.clip || data.bbox.empty())
222 std::ostringstream os;
223 if (!data.bbox.empty())
224 os << "bb=" << data.bbox << ',';
231 string const ResizeLatexOption::option_impl() const
233 if (data.no_resize())
236 std::ostringstream os;
237 if (data.usingScale()) {
238 double scl = strToDbl(data.scale);
239 if (!float_equal(scl, 100.0, 0.05))
240 os << "scale=" << scl / 100.0 << ',';
244 if (!data.width.zero())
245 os << "width=" << data.width.asLatexString() << ',';
246 if (!data.height.zero())
247 os << "height=" << data.height.asLatexString() << ',';
248 if (data.keepAspectRatio)
249 os << "keepaspectratio,";
255 string const RotationLatexOption ::option_impl() const
257 if (data.no_rotation())
260 std::ostringstream os;
261 os << "angle=" << data.angle << ',';
263 if (data.origin() != RotationData::DEFAULT)
264 os << "origin=" << data.origin() << ',';
270 string const sanitizeDocBookOption(string const & input)
276 string const sanitizeLatexOption(string const & input)
278 string::const_iterator begin = input.begin();
279 string::const_iterator end = input.end();
280 string::const_iterator it = begin;
282 // Strip any leading commas
283 // "[,,,,foo..." -> "foo..." ("foo..." may be empty)
286 static boost::regex const front("^( *[[],*)(.*)$");
288 regex_match(it, end, what, front, boost::match_partial);
289 if (!what[0].matched) {
290 lyxerr << "Unable to sanitize LaTeX \"Option\": "
296 // Replace any consecutive commas with a single one
297 // "foo,,,,bar" -> "foo,bar"
298 // with iterator now pointing to 'b'
299 static boost::regex const commas("([^,]*)(,,*)(.*)$");
301 regex_match(it, end, what, commas, boost::match_partial);
302 if (!what[0].matched) {
303 output += string(it, end);
306 output += what.str(1) + ",";
310 // Strip any trailing commas
311 // "...foo,,,]" -> "...foo" ("...foo,,," may be empty)
312 static boost::regex const back("^(.*[^,])?,*[]] *$");
313 regex_match(output, what, back);
314 if (!what[0].matched) {
315 lyxerr << "Unable to sanitize LaTeX \"Option\": "
319 output = what.str(1);
321 // Remove any surrounding whitespace
322 output = lyx::support::trim(output);
324 // If the thing is empty, leave it so, else wrap it in square brackets.
325 return output.empty() ? output : "[" + output + "]";
329 string const sanitizeLinuxDocOption(string const & input)
337 template <typename Factory, typename Data, typename Transformer>
338 void extractIt(boost::any const & any_factory,
339 Data const & data, Transformer & transformer)
341 if (any_factory.type() != typeid(Factory))
344 Factory factory = boost::any_cast<Factory>(any_factory);
345 if (!factory.empty())
346 transformer = factory(data);
352 TransformCommand::ptr_type
353 TransformStore::getCommandTransformer(RotationData const & data) const
355 TransformCommand::ptr_type ptr;
357 extractIt<RotationCommandFactory>(any_factory, data, ptr);
362 TransformCommand::ptr_type
363 TransformStore::getCommandTransformer(ResizeData const & data) const
365 TransformCommand::ptr_type ptr;
367 extractIt<ResizeCommandFactory>(any_factory, data, ptr);
372 TransformOption::ptr_type
373 TransformStore::getOptionTransformer(RotationData const & data) const
375 TransformOption::ptr_type ptr;
377 extractIt<RotationOptionFactory>(any_factory, data, ptr);
382 TransformOption::ptr_type
383 TransformStore::getOptionTransformer(ResizeData const & data) const
385 TransformOption::ptr_type ptr;
387 extractIt<ResizeOptionFactory>(any_factory, data, ptr);
392 TransformOption::ptr_type
393 TransformStore::getOptionTransformer(ClipData const & data) const
395 TransformOption::ptr_type ptr;
397 extractIt<ClipOptionFactory>(any_factory, data, ptr);
403 TransformOption::ptr_type
404 TransformStore::getOptionTransformer(string const & data) const
406 TransformOption::ptr_type ptr;
408 extractIt<ExtraOptionFactory>(any_factory, data, ptr);
415 OriginTranslator const initOriginTranslator()
417 OriginTranslator translator(RotationData::DEFAULT, "default");
418 translator.addPair(RotationData::TOPLEFT, "topleft");
419 translator.addPair(RotationData::BOTTOMLEFT, "bottomleft");
420 translator.addPair(RotationData::BASELINELEFT, "baselineleft");
421 translator.addPair(RotationData::CENTER, "center");
422 translator.addPair(RotationData::TOPCENTER, "topcenter");
423 translator.addPair(RotationData::BOTTOMCENTER, "bottomcenter");
424 translator.addPair(RotationData::BASELINECENTER, "baselinecenter");
425 translator.addPair(RotationData::TOPRIGHT, "topright");
426 translator.addPair(RotationData::BOTTOMRIGHT, "bottomright");
427 translator.addPair(RotationData::BASELINERIGHT, "baselineright");
432 OriginTranslator const & originTranslator()
434 static OriginTranslator const translator = initOriginTranslator();
440 } // namespace external