Ejemplo n.º 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());
		}
	}
}
/** Evaluates the special dvisvgm:bbox.
 *  variant 1: dvisvgm:bbox [r[el]] <width> <height> [<depth>]
 *  variant 2: dvisvgm:bbox a[bs] <x1> <y1> <x2> <y2>
 *  variant 3: dvisvgm:bbox f[ix] <x1> <y1> <x2> <y2>
 *  variant 4: dvisvgm:bbox n[ew] <name> */
void DvisvgmSpecialHandler::processBBox (InputReader &ir, SpecialActions *actions) {
    const double pt2bp = 72/72.27;
    ir.skipSpace();
    int c = ir.peek();
    if (isalpha(c)) {
        while (!isspace(ir.peek()))  // skip trailing characters
            ir.get();
        if (c == 'n') {
            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') {
            double p[4];
            for (int i=0; i < 4; i++)
                p[i] = ir.getDouble()*pt2bp;
            BoundingBox b(p[0], p[1], p[2], p[3]);
            if (c == 'a')
                actions->embed(b);
            else {
                actions->bbox() = b;
                actions->bbox().lock();
            }
        }
    }
    else
        c = 'r';   // no mode specifier => relative box parameters

    if (c == 'r') {
        double w = ir.getDouble()*pt2bp;
        double h = ir.getDouble()*pt2bp;
        double d = ir.getDouble()*pt2bp;
        update_bbox(w, h, d, actions);
    }
}
Ejemplo n.º 3
0
/** Reads a length (value + unit) and returns its value in PS points (bp).
 *  If no unit is specified, TeX points are assumed. */
static double read_length (InputReader &in) {
	double val = in.getDouble();
	string unitstr;
	if (isalpha(in.peek())) unitstr += in.get();
	if (isalpha(in.peek())) unitstr += in.get();
	Length::Unit unit = Length::Unit::PT;
	try {
		unit = Length::stringToUnit(unitstr);
	}
	catch (UnitException &e) {
	}
	return Length(val, unit).bp();
}
Ejemplo n.º 4
0
/** Parses a single line in dvips mapfile format.
 *  @param[in] ir the input stream must be assigned to this reader */
void MapLine::parseDVIPSLine (InputReader &ir) {
	ir.skipSpace();
	if (ir.peek() != '<' && ir.peek() != '"')
		_psname = ir.getString();
	ir.skipSpace();
	while (ir.peek() == '<' || ir.peek() == '"') {
		if (ir.peek() == '<') {
			ir.get();
			if (ir.peek() == '[')
				ir.get();
			string name = ir.getString();
			if (name.length() > 4 && name.substr(name.length()-4) == ".enc")
				_encname = name.substr(0, name.length()-4);
			else
				_fontfname = name;
		}
		else {  // ir.peek() == '"' => list of PS font operators
			string options = ir.getQuotedString('"');
			StringInputBuffer sib(options);
			BufferInputReader sir(sib);
			while (!sir.eof()) {
				double number;
				if (sir.parseDouble(number)) {
					// operator with preceding numeric parameter (value opstr)
					string opstr = sir.getString();
					if (opstr == "SlantFont")
						_slant = number;
					else if (opstr == "ExtendFont")
						_extend = number;
				}
				else {
					// operator without parameter => skip for now
					sir.getString();
				}
			}
		}
		ir.skipSpace();
	}
}
Ejemplo n.º 5
0
/** Reads characters from an input stream until the pattern string or EOF is reached.
 *  The matching string is read too if found. An empty pattern matches any character, i.e.
 *  reading stops after the first character.
 *  @return true if the pattern was found */
bool StringMatcher::match (InputReader &ir) {
	int c;
	int i=0;
	const int len = static_cast<int>(_pattern.length());
	_charsRead = 0;
	while ((c = ir.get()) >= 0) {
		_charsRead++;
		while (i >= 0 && c != _pattern[i])
			i = _borders[i];
		if (++i == len)
			return true;
	}
	return false;
}
Ejemplo n.º 6
0
/** Reads characters from an input stream until the pattern string or EOF is reached
 *  and returns them as a string. The matching string is also appended to the returned string. */
string StringMatcher::read (InputReader &ir) {
	string ret;
	int c;
	int i=0;
	const int len = static_cast<int>(_pattern.length());
	while ((c = ir.get()) >= 0) {
		ret += char(c);
		while (i >= 0 && c != _pattern[i])
			i = _borders[i];
		if (++i == len)
			break;
	}
	_charsRead = ret.length();
	return ret;
}
Ejemplo n.º 7
0
/** Handles the "line" command that draws a straight line between two points
 *  from the point list. */
void EmSpecialHandler::line (InputReader &ir, SpecialActions& actions) {
	int pointnum1 = ir.getInt();
	int cut1 = 'p';
	if (isalpha(ir.peek()))
		cut1 = ir.get();
	ir.getPunct();
	int pointnum2 = ir.getInt();
	int cut2 = 'p';
	if (isalpha(ir.peek()))
		cut2 = ir.get();
	double linewidth = _linewidth;
	if (ir.getPunct() == ',')
		linewidth = read_length(ir);
	auto it1=_points.find(pointnum1);
	auto it2=_points.find(pointnum2);
	if (it1 != _points.end() && it2 != _points.end())
		create_line(it1->second, it2->second, char(cut1), char(cut2), linewidth, actions);
	else {
		// Line endpoints don't necessarily have to be defined before
		// a line definition. If a point isn't defined yet, we put the line
		// in a wait list and process the lines at the end of the page.
		_lines.emplace_back(Line(pointnum1, pointnum2, char(cut1), char(cut2), linewidth));
	}
}
Ejemplo n.º 8
0
static string read_entry (InputReader &in) {
	string entry;
	bool accept_slashes=true;
	while (!in.eof() && ((in.peek() == '/' && accept_slashes) || valid_name_char(in.peek()))) {
		if (in.peek() != '/')
			accept_slashes = false;
		entry += char(in.get());
	}
	if (entry.length() > 1) {
		// strip leading slashes
		// According to the PostScript specification, a single slash without further
		// following characters is a valid name.
		size_t n=0;
		while (n < entry.length() && entry[n] == '/')
			n++;
		entry = entry.substr(n);
	}
	return entry;
}
Ejemplo n.º 9
0
/** Parses a single line in dvipdfmx mapfile format.
 *  @param[in] ir the input stream must be assigned to this reader */
void MapLine::parseDVIPDFMLine (InputReader &ir) {
	ir.skipSpace();
	if (ir.peek() != '-') {
		_encname = ir.getString();
		if (_encname == "default" || _encname == "none")
			_encname.clear();
	}
	ir.skipSpace();
		if (ir.peek() != '-')
		_fontfname = ir.getString();
	if (!_fontfname.empty()) {
		parseFilenameOptions(_fontfname);
	}
	ir.skipSpace();
	while (ir.peek() == '-') {
		ir.get();
		int option = ir.get();
		if (!isprint(option))
			throw MapLineException("option character expected");
		ir.skipSpace();
		switch (option) {
			case 's': // slant
				if (!ir.parseDouble(_slant))
					throw_number_expected('s');
				break;
			case 'e': // extend
				if (!ir.parseDouble(_extend))
					throw_number_expected('e');
				break;
			case 'b': // bold
				if (!ir.parseDouble(_bold))
					throw_number_expected('b');
				break;
			case 'r': //remap (deprecated)
				break;
			case 'i': // ttc index
				if (!ir.parseInt(_fontindex, false))
					throw_number_expected('i', true);
				break;
			case 'p': // UCS plane
				int dummy;
				if (!ir.parseInt(dummy, false))
					throw_number_expected('p', true);
				break;
			case 'u': // to unicode
				ir.getString();
				break;
			case 'v': // stemV
				int stemv;
				if (!ir.parseInt(stemv, true))
					throw_number_expected('v', true);
				break;
			case 'm': // map single chars
				ir.skipUntil("-");
				break;
			case 'w': // writing mode (horizontal=0, vertical=1)
				int vertical;
				if (!ir.parseInt(vertical, false))
					throw_number_expected('w', true);
				break;
			default:
				ostringstream oss;
				oss << "invalid option: -" << option;
				throw MapLineException(oss.str());
		}
		ir.skipSpace();
	}
}