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/translator.h"
21 #include <boost/regex.hpp>
22 #include "support/std_sstream.h"
23 #include <cmath> // std::abs
25 using lyx::support::float_equal;
33 string const ExtraData::get(string const & id) const
35 std::map<string, string>::const_iterator it = data_.find(id);
36 return it == data_.end() ? string() : it->second;
40 void ExtraData::set(string const & id, string const & data)
46 bool ResizeData::no_resize() const
48 return float_equal(scale, 0.0, 0.05) &&
49 width.zero() && height.zero();
53 bool RotationData::no_rotation() const
55 return (std::abs(angle()) < 0.1);
59 void RotationData::angle(double a)
61 // Ensure that angle_ lies in the range -360 < angle_ < 360.
62 int const multiples = int(a) / 360;
63 angle_ = a - (multiples * 360);
69 typedef Translator<RotationData::OriginType, string> OriginTranslator;
70 OriginTranslator const & originTranslator();
75 void RotationData::origin(string const & o)
77 origin_ = originTranslator().find(o);
81 string const RotationData::originString() const
83 return originTranslator().find(origin_);
87 string const ResizeLatexCommand::front_impl() const
92 std::ostringstream os;
93 if (!float_equal(data.scale, 0.0, 0.05)) {
94 double const scl = data.scale / 100.0;
95 os << "\\scalebox{" << scl << "}{" << scl << "}{";
98 << (data.width.zero() ?
99 "!" : data.width.asLatexString()) << "}{"
100 << (data.height.zero() ?
101 "!" : data.height.asLatexString()) << "}{";
107 string const ResizeLatexCommand::back_impl() const
109 if (data.no_resize())
118 std::ostream & operator<<(std::ostream & os, RotationData::OriginType type)
121 case RotationData::DEFAULT:
122 case RotationData::CENTER:
124 case RotationData::TOPLEFT:
125 case RotationData::TOPCENTER:
126 case RotationData::TOPRIGHT:
129 case RotationData::BOTTOMLEFT:
130 case RotationData::BOTTOMCENTER:
131 case RotationData::BOTTOMRIGHT:
134 case RotationData::BASELINELEFT:
135 case RotationData::BASELINECENTER:
136 case RotationData::BASELINERIGHT:
142 case RotationData::DEFAULT:
144 case RotationData::TOPLEFT:
145 case RotationData::BOTTOMLEFT:
146 case RotationData::BASELINELEFT:
149 case RotationData::CENTER:
150 case RotationData::TOPCENTER:
151 case RotationData::BOTTOMCENTER:
152 case RotationData::BASELINECENTER:
155 case RotationData::TOPRIGHT:
156 case RotationData::BOTTOMRIGHT:
157 case RotationData::BASELINERIGHT:
168 string const RotationLatexCommand::front_impl() const
170 if (data.no_rotation())
173 std::ostringstream os;
176 if (data.origin() != RotationData::DEFAULT)
177 os << "[origin=" << data.origin() << ']';
179 os << '{' << data.angle() << "}{";
184 string const RotationLatexCommand::back_impl() const
186 if (data.no_rotation())
193 string const ClipLatexOption::option_impl() const
195 if (!data.clip || data.bbox.empty())
198 std::ostringstream os;
199 if (!data.bbox.empty())
200 os << "bb=" << data.bbox << ',';
207 string const ResizeLatexOption::option_impl() const
209 if (data.no_resize())
212 std::ostringstream os;
213 if (!float_equal(data.scale, 0.0, 0.05)) {
214 if (!float_equal(data.scale, 100.0, 0.05))
215 os << "scale=" << data.scale / 100.0 << ',';
219 if (!data.width.zero())
220 os << "width=" << data.width.asLatexString() << ',';
221 if (!data.height.zero())
222 os << "height=" << data.height.asLatexString() << ',';
223 if (data.keepAspectRatio)
224 os << "keepaspectratio,";
230 string const RotationLatexOption ::option_impl() const
232 if (data.no_rotation())
235 std::ostringstream os;
236 os << "angle=" << data.angle() << ',';
238 if (data.origin() != RotationData::DEFAULT)
239 os << "origin=" << data.origin() << ',';
245 string const sanitizeDocBookOption(string const & input)
251 string const sanitizeLatexOption(string const & input)
253 string::const_iterator begin = input.begin();
254 string::const_iterator end = input.end();
255 string::const_iterator it = begin;
257 // Strip any leading commas
258 // "[,,,,foo..." -> "foo..."
261 boost::regex const front("^( *[[],*)(.*)$");
263 regex_match(it, end, what, front, boost::match_partial);
264 if (!what[0].matched) {
265 lyxerr << "Unable to sanitize LaTeX \"Option\": "
271 // Replace any consecutive commas with a single one
272 // "foo,,,,bar" -> "foo,bar"
273 // with iterator now pointing to 'b'
274 boost::regex const commas("([^,]*)(,,*)(.*)$");
276 regex_match(it, end, what, commas, boost::match_partial);
277 if (!what[0].matched) {
278 output += string(it, end);
281 output += what.str(1) + ",";
285 // Strip any trailing commas
286 // "...foo,,,]" -> "...foo"
287 boost::regex const back("^(.*[^,])(,*[]] *)$");
288 regex_match(output, what, back);
289 if (!what[0].matched) {
290 lyxerr << "Unable to sanitize LaTeX \"Option\": "
294 output = what.str(1);
296 // Remove any surrounding whitespace
297 output = lyx::support::trim(output);
299 // If the thing is empty, leave it so, else wrap it in square brackets.
300 return output.empty() ? output : "[" + output + "]";
304 string const sanitizeLinuxDocOption(string const & input)
312 template <typename Factory, typename Data, typename Transformer>
313 void extractIt(boost::any const & any_factory,
314 Data const & data, Transformer & transformer)
316 if (any_factory.type() != typeid(Factory))
319 Factory factory = boost::any_cast<Factory>(any_factory);
320 if (!factory.empty())
321 transformer = factory(data);
327 TransformCommand::ptr_type
328 TransformStore::getCommandTransformer(RotationData const & data) const
330 TransformCommand::ptr_type ptr;
332 extractIt<RotationCommandFactory>(any_factory, data, ptr);
337 TransformCommand::ptr_type
338 TransformStore::getCommandTransformer(ResizeData const & data) const
340 TransformCommand::ptr_type ptr;
342 extractIt<ResizeCommandFactory>(any_factory, data, ptr);
347 TransformOption::ptr_type
348 TransformStore::getOptionTransformer(RotationData const & data) const
350 TransformOption::ptr_type ptr;
352 extractIt<RotationOptionFactory>(any_factory, data, ptr);
357 TransformOption::ptr_type
358 TransformStore::getOptionTransformer(ResizeData const & data) const
360 TransformOption::ptr_type ptr;
362 extractIt<ResizeOptionFactory>(any_factory, data, ptr);
367 TransformOption::ptr_type
368 TransformStore::getOptionTransformer(ClipData const & data) const
370 TransformOption::ptr_type ptr;
372 extractIt<ClipOptionFactory>(any_factory, data, ptr);
378 TransformOption::ptr_type
379 TransformStore::getOptionTransformer(string const & data) const
381 TransformOption::ptr_type ptr;
383 extractIt<ExtraOptionFactory>(any_factory, data, ptr);
390 OriginTranslator const initOriginTranslator()
392 OriginTranslator translator(RotationData::DEFAULT, "default");
393 translator.addPair(RotationData::TOPLEFT, "topleft");
394 translator.addPair(RotationData::BOTTOMLEFT, "bottomleft");
395 translator.addPair(RotationData::BASELINELEFT, "baselineleft");
396 translator.addPair(RotationData::CENTER, "center");
397 translator.addPair(RotationData::TOPCENTER, "topcenter");
398 translator.addPair(RotationData::BOTTOMCENTER, "bottomcenter");
399 translator.addPair(RotationData::BASELINECENTER, "baselinecenter");
400 translator.addPair(RotationData::TOPRIGHT, "topright");
401 translator.addPair(RotationData::BOTTOMRIGHT, "bottomright");
402 translator.addPair(RotationData::BASELINERIGHT, "baselineright");
407 OriginTranslator const & originTranslator()
409 static OriginTranslator const translator = initOriginTranslator();
415 } // namespace external