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>
23 #include <cmath> // std::abs
26 using lyx::support::float_equal;
34 string const ExtraData::get(string const & id) const
36 std::map<string, string>::const_iterator it = data_.find(id);
37 return it == data_.end() ? string() : it->second;
41 void ExtraData::set(string const & id, string const & data)
47 bool ResizeData::no_resize() const
49 return !usingScale() && width.zero() && height.zero();
53 bool ResizeData::usingScale() const
55 return !float_equal(scale, 0.0, 0.05);
59 bool RotationData::no_rotation() const
61 return (std::abs(angle()) < 0.1);
65 void RotationData::angle(double a)
67 // Ensure that angle_ lies in the range -360 < angle_ < 360.
68 int const multiples = int(a) / 360;
69 angle_ = a - (multiples * 360);
75 typedef Translator<RotationData::OriginType, string> OriginTranslator;
76 OriginTranslator const & originTranslator();
81 void RotationData::origin(string const & o)
83 origin_ = originTranslator().find(o);
87 string const RotationData::originString() const
89 return originTranslator().find(origin_);
93 string const ResizeLatexCommand::front_impl() const
98 std::ostringstream os;
99 if (data.usingScale()) {
100 double const scl = data.scale / 100.0;
101 os << "\\scalebox{" << scl << "}{" << scl << "}{";
105 if (data.keepAspectRatio) {
106 if (data.width.inPixels(10) > data.height.inPixels(10))
107 width = data.width.asLatexString();
109 height = data.height.asLatexString();
111 if (!data.width.zero())
112 width = data.width.asLatexString();
113 if (!data.height.zero())
114 height = data.height.asLatexString();
125 string const ResizeLatexCommand::back_impl() const
127 if (data.no_resize())
136 std::ostream & operator<<(std::ostream & os, RotationData::OriginType type)
139 case RotationData::DEFAULT:
140 case RotationData::CENTER:
142 case RotationData::TOPLEFT:
143 case RotationData::TOPCENTER:
144 case RotationData::TOPRIGHT:
147 case RotationData::BOTTOMLEFT:
148 case RotationData::BOTTOMCENTER:
149 case RotationData::BOTTOMRIGHT:
152 case RotationData::BASELINELEFT:
153 case RotationData::BASELINECENTER:
154 case RotationData::BASELINERIGHT:
160 case RotationData::DEFAULT:
162 case RotationData::TOPLEFT:
163 case RotationData::BOTTOMLEFT:
164 case RotationData::BASELINELEFT:
167 case RotationData::CENTER:
168 case RotationData::TOPCENTER:
169 case RotationData::BOTTOMCENTER:
170 case RotationData::BASELINECENTER:
173 case RotationData::TOPRIGHT:
174 case RotationData::BOTTOMRIGHT:
175 case RotationData::BASELINERIGHT:
186 string const RotationLatexCommand::front_impl() const
188 if (data.no_rotation())
191 std::ostringstream os;
194 if (data.origin() != RotationData::DEFAULT)
195 os << "[origin=" << data.origin() << ']';
197 os << '{' << data.angle() << "}{";
202 string const RotationLatexCommand::back_impl() const
204 if (data.no_rotation())
211 string const ClipLatexOption::option_impl() const
213 if (!data.clip || data.bbox.empty())
216 std::ostringstream os;
217 if (!data.bbox.empty())
218 os << "bb=" << data.bbox << ',';
225 string const ResizeLatexOption::option_impl() const
227 if (data.no_resize())
230 std::ostringstream os;
231 if (data.usingScale()) {
232 if (!float_equal(data.scale, 100.0, 0.05))
233 os << "scale=" << data.scale / 100.0 << ',';
237 if (!data.width.zero())
238 os << "width=" << data.width.asLatexString() << ',';
239 if (!data.height.zero())
240 os << "height=" << data.height.asLatexString() << ',';
241 if (data.keepAspectRatio)
242 os << "keepaspectratio,";
248 string const RotationLatexOption ::option_impl() const
250 if (data.no_rotation())
253 std::ostringstream os;
254 os << "angle=" << data.angle() << ',';
256 if (data.origin() != RotationData::DEFAULT)
257 os << "origin=" << data.origin() << ',';
263 string const sanitizeDocBookOption(string const & input)
269 string const sanitizeLatexOption(string const & input)
271 string::const_iterator begin = input.begin();
272 string::const_iterator end = input.end();
273 string::const_iterator it = begin;
275 // Strip any leading commas
276 // "[,,,,foo..." -> "foo..." ("foo..." may be empty)
279 static boost::regex const front("^( *[[],*)(.*)$");
281 regex_match(it, end, what, front, boost::match_partial);
282 if (!what[0].matched) {
283 lyxerr << "Unable to sanitize LaTeX \"Option\": "
289 // Replace any consecutive commas with a single one
290 // "foo,,,,bar" -> "foo,bar"
291 // with iterator now pointing to 'b'
292 static boost::regex const commas("([^,]*)(,,*)(.*)$");
294 regex_match(it, end, what, commas, boost::match_partial);
295 if (!what[0].matched) {
296 output += string(it, end);
299 output += what.str(1) + ",";
303 // Strip any trailing commas
304 // "...foo,,,]" -> "...foo" ("...foo,,," may be empty)
305 static boost::regex const back("^(.*[^,])?,*[]] *$");
306 regex_match(output, what, back);
307 if (!what[0].matched) {
308 lyxerr << "Unable to sanitize LaTeX \"Option\": "
312 output = what.str(1);
314 // Remove any surrounding whitespace
315 output = lyx::support::trim(output);
317 // If the thing is empty, leave it so, else wrap it in square brackets.
318 return output.empty() ? output : "[" + output + "]";
322 string const sanitizeLinuxDocOption(string const & input)
330 template <typename Factory, typename Data, typename Transformer>
331 void extractIt(boost::any const & any_factory,
332 Data const & data, Transformer & transformer)
334 if (any_factory.type() != typeid(Factory))
337 Factory factory = boost::any_cast<Factory>(any_factory);
338 if (!factory.empty())
339 transformer = factory(data);
345 TransformCommand::ptr_type
346 TransformStore::getCommandTransformer(RotationData const & data) const
348 TransformCommand::ptr_type ptr;
350 extractIt<RotationCommandFactory>(any_factory, data, ptr);
355 TransformCommand::ptr_type
356 TransformStore::getCommandTransformer(ResizeData const & data) const
358 TransformCommand::ptr_type ptr;
360 extractIt<ResizeCommandFactory>(any_factory, data, ptr);
365 TransformOption::ptr_type
366 TransformStore::getOptionTransformer(RotationData const & data) const
368 TransformOption::ptr_type ptr;
370 extractIt<RotationOptionFactory>(any_factory, data, ptr);
375 TransformOption::ptr_type
376 TransformStore::getOptionTransformer(ResizeData const & data) const
378 TransformOption::ptr_type ptr;
380 extractIt<ResizeOptionFactory>(any_factory, data, ptr);
385 TransformOption::ptr_type
386 TransformStore::getOptionTransformer(ClipData const & data) const
388 TransformOption::ptr_type ptr;
390 extractIt<ClipOptionFactory>(any_factory, data, ptr);
396 TransformOption::ptr_type
397 TransformStore::getOptionTransformer(string const & data) const
399 TransformOption::ptr_type ptr;
401 extractIt<ExtraOptionFactory>(any_factory, data, ptr);
408 OriginTranslator const initOriginTranslator()
410 OriginTranslator translator(RotationData::DEFAULT, "default");
411 translator.addPair(RotationData::TOPLEFT, "topleft");
412 translator.addPair(RotationData::BOTTOMLEFT, "bottomleft");
413 translator.addPair(RotationData::BASELINELEFT, "baselineleft");
414 translator.addPair(RotationData::CENTER, "center");
415 translator.addPair(RotationData::TOPCENTER, "topcenter");
416 translator.addPair(RotationData::BOTTOMCENTER, "bottomcenter");
417 translator.addPair(RotationData::BASELINECENTER, "baselinecenter");
418 translator.addPair(RotationData::TOPRIGHT, "topright");
419 translator.addPair(RotationData::BOTTOMRIGHT, "bottomright");
420 translator.addPair(RotationData::BASELINERIGHT, "baselineright");
425 OriginTranslator const & originTranslator()
427 static OriginTranslator const translator = initOriginTranslator();
433 } // namespace external