예제 #1
0
/** Evaluates the special dvisvgm:bbox.
 *  variant 1: dvisvgm:bbox [r[el]] <width> <height> [<depth>] [transform]
 *  variant 2: dvisvgm:bbox a[bs] <x1> <y1> <x2> <y2> [transform]
 *  variant 3: dvisvgm:bbox f[ix] <x1> <y1> <x2> <y2> [transform]
 *  variant 4: dvisvgm:bbox n[ew] <name>
 *  variant 5: dvisvgm:bbox lock | unlock */
void DvisvgmSpecialHandler::processBBox (InputReader &ir, SpecialActions &actions) {
	ir.skipSpace();
	if (ir.check("lock"))
		actions.bbox().lock();
	else if (ir.check("unlock"))
		actions.bbox().unlock();
	else {
		int c = ir.peek();
		try {
			if (!isalpha(c))
				c = 'r';   // no mode specifier => relative box parameters
			else {
				while (!isspace(ir.peek()))  // skip trailing characters
					ir.get();
				if (c == 'n') {   // "new": create new local bounding box
					ir.skipSpace();
					string name;
					while (isalnum(ir.peek()))
						name += char(ir.get());
					ir.skipSpace();
					if (!name.empty() && ir.eof())
						actions.bbox(name, true); // create new user box
				}
				else if (c == 'a' || c == 'f') {  // "abs" or "fix"
					Length lengths[4];
					for (Length &len : lengths)
						len = read_length(ir);
					BoundingBox b(lengths[0], lengths[1], lengths[2], lengths[3]);
					ir.skipSpace();
					if (ir.check("transform"))
						b.transform(actions.getMatrix());
					if (c == 'a')
						actions.embed(b);
					else {
						actions.bbox() = b;
						actions.bbox().lock();
					}
				}
			}
			if (c == 'r') {
				Length w = read_length(ir);
				Length h = read_length(ir);
				Length d = read_length(ir);
				ir.skipSpace();
				update_bbox(w, h, d, ir.check("transform"), actions);
			}
		}
		catch (const UnitException &e) {
			throw SpecialException(string("dvisvgm:bbox: ") + e.what());
		}
	}
}
예제 #2
0
void DvisvgmSpecialHandler::dviEndPage (unsigned, SpecialActions &actions) {
	_defsParser.flush(actions);
	_pageParser.flush(actions);
	actions.bbox().unlock();
	for (auto &strvecpair : _macros) {
		StringVector &vec = strvecpair.second;
		for (string &str : vec) {
			// activate locked parts of a pattern again
			if (str[0] == 'L')
				str[0] = 'D';
		}
	}
}
예제 #3
0
/** Applies the previously recorded size to a given page. */
void PapersizeSpecialHandler::applyPaperSize (unsigned pageno, SpecialActions &actions) {
	// find page n >= pageno that contains a papersize special
	auto lb_it = lower_bound(_pageSizes.begin(), _pageSizes.end(), PageSize(pageno, DoublePair()),
		[](const PageSize &ps1, const PageSize &ps2) {
			// order PageSize objects by page number
			return ps1.first < ps2.first;
		});
	auto it = _pageSizes.end();
	if (lb_it != _pageSizes.end() && lb_it->first == pageno)
		it = lb_it;                        // if current page contains a papersize special, use it
	else if (lb_it != _pageSizes.begin()) // no papersize special on current page?
		it = lb_it-1;                      // => use the one on the nearest preceding page
	if (it == _pageSizes.end())
		Message::wstream(true) << "no valid papersize special found\n";
	else {
		DoublePair size = it->second;
		const double border = -72;  // DVI standard: coordinates of upper left paper corner are (-72bp, -72bp)
		actions.bbox() = BoundingBox(border, border, size.first+border, size.second+border);
	}
}
예제 #4
0
/** Replaces constants of the form {?name} by their corresponding value.
 *  @param[in,out] str text to expand
 *  @param[in] actions interfcae to the world outside the special handler */
static void expand_constants (string &str, SpecialActions &actions) {
	bool repl_bbox = true;
	while (repl_bbox) {
		size_t pos = str.find("{?bbox ");
		if (pos == string::npos)
			repl_bbox = false;
		else {
			size_t endpos = pos+7;
			while (endpos < str.length() && isalnum(str[endpos]))
				++endpos;
			if (str[endpos] == '}') {
				BoundingBox &box=actions.bbox(str.substr(pos+7, endpos-pos-7));
				str.replace(pos, endpos-pos+1, box.toSVGViewBox());
			}
			else
				repl_bbox = false;
		}
	}
	struct Constant {
		const char *name;
		string val;
	};
	const array<Constant, 5> constants {{
		{"x",      XMLString(actions.getX())},
		{"y",      XMLString(actions.getY())},
		{"color",  actions.getColor().svgColorString()},
		{"matrix", actions.getMatrix().toSVG()},
		{"nl",    "\n"},
	}};
	for (const Constant &constant : constants) {
		const string pattern = string("{?")+constant.name+"}";
		size_t pos = str.find(pattern);
		while (pos != string::npos) {
			str.replace(pos, strlen(constant.name)+3, constant.val);
			pos = str.find(pattern, pos+constant.val.length());  // look for further matches
		}
	}
}