Example #1
0
static bool ParseFontFamily(const char* s, size_t len, FontID& v) {
	bool   onFont = false;
	char   buf[64];
	size_t bufPos = 0;
	for (size_t i = 0; true; i++) {
		if (onFont) {
			if (s[i] == ',' || i == len) {
				buf[bufPos] = 0;
				v           = Global()->FontStore->InsertByFacename(buf);
				if (v != FontIDNull)
					return true;
				onFont = false;
				bufPos = 0;
			} else {
				buf[bufPos++] = s[i];
			}
			if (i == len)
				break;
		} else {
			if (i == len)
				break;
			if (IsWhitespace(s[i]))
				continue;
			onFont        = true;
			buf[bufPos++] = s[i];
		}
		if (bufPos >= arraysize(buf)) {
			ParseFail("Parse failed, font name too long (>63): '%*.s'\n", (int) len, s);
			return false;
		}
	}
	// not sure whether we should do this. One might want no font to be set instead.
	v = Global()->FontStore->GetFallbackFontID();
	return true;
}
Example #2
0
bool Color::Parse(const char* s, size_t len, Color& v) {
	Color c = Color::RGBA(0, 0, 0, 0);
	s++;
	// #rgb
	// #rgba
	// #rrggbb
	// #rrggbbaa
	if (len == 4) {
		c.r = ParseHexCharSingle(s + 0);
		c.g = ParseHexCharSingle(s + 1);
		c.b = ParseHexCharSingle(s + 2);
		c.a = 255;
		//Trace( "color %s -> %d\n", s, (int) c.r );
	} else if (len == 5) {
		c.r = ParseHexCharSingle(s + 0);
		c.g = ParseHexCharSingle(s + 1);
		c.b = ParseHexCharSingle(s + 2);
		c.a = ParseHexCharSingle(s + 3);
	} else if (len == 7) {
		c.r = ParseHexCharPair(s + 0);
		c.g = ParseHexCharPair(s + 2);
		c.b = ParseHexCharPair(s + 4);
		c.a = 255;
	} else if (len == 9) {
		c.r = ParseHexCharPair(s + 0);
		c.g = ParseHexCharPair(s + 2);
		c.b = ParseHexCharPair(s + 4);
		c.a = ParseHexCharPair(s + 6);
	} else {
		ParseFail("Parse failed, invalid color %.*s\n", (int) len, s);
		return false;
	}
	v = c;
	return true;
}
Example #3
0
bool Size::Parse(const char* s, size_t len, Size& v) {
	// 1.23px
	// 1.23ep
	// 1.23pt
	// 1.23%
	// 0
	char digits[100];
	if (len > 30) {
		ParseFail("Parse failed, size too big (>30 characters)\n");
		return false;
	}
	Size   x      = Size::Pixels(0);
	size_t nondig = 0;
	for (; nondig < len; nondig++) {
		digits[nondig] = s[nondig];
		if (!IsNumeric(s[nondig]))
			break;
	}
	digits[nondig] = 0;
	x.Val          = (float) atof(digits);
	if (nondig == len) {
		if (len == 1 && s[0] == '0') {
			// ok
		} else {
			ParseFail("Parse failed, invalid size: %.*s\n", (int) len, s);
			return false;
		}
	} else {
		if (s[nondig] == '%') {
			x.Type = Size::PERCENT;
		} else if (s[nondig] == 'p' && len - nondig >= 2) {
			if (s[nondig + 1] == 'x')
				x.Type = Size::PX;
			else if (s[nondig + 1] == 't')
				x.Type = Size::PT;
			else {
				ParseFail("Parse failed, invalid size: %.*s\n", (int) len, s);
				return false;
			}
		} else if (s[nondig] == 'e' && len - nondig >= 2 && s[nondig + 1] == 'p') {
			x.Type = Size::EP;
		}
	}
	v = x;
	return true;
}
Example #4
0
static bool ParseDirect(const char* s, size_t len, bool (*parseFunc)(const char* s, size_t len, Style& style), Style& style) {
	if (parseFunc(s, len, style)) {
		return true;
	} else {
		ParseFail("Parse failed on: '%.*s'\n", (int) len, s);
		return false;
	}
}
Example #5
0
static bool ParseCompound(const char* s, size_t len, bool (*parseFunc)(const char* s, size_t len, T& t), StyleCategories cat, Style& style) {
	T val;
	if (parseFunc(s, len, val)) {
		style.Set(cat, val);
		return true;
	} else {
		ParseFail("Parse failed, unknown value: '%.*s'\n", (int) len, s);
		return false;
	}
}
Example #6
0
static bool ParseBool(const char* s, size_t len, StyleCategories cat, Style& style) {
	bool val;
	if (len == 4 && s[0] == 't')
		val = true;
	else if (len == 5 && s[0] == 'f')
		val = false;
	else {
		ParseFail("Parse failed, illegal boolean value: '%.*s'. Valid values are 'true' and 'false'.\n", (int) len, s);
		return false;
	}
	StyleAttrib attrib;
	attrib.SetBool(cat, val);
	style.Set(attrib);
	return true;
}
Example #7
0
bool DomNode::StyleParsef(const char* t, ...) {
	char    buff[8192];
	va_list va;
	va_start(va, t);
	uint32_t r = vsnprintf(buff, arraysize(buff), t, va);
	va_end(va);
	buff[arraysize(buff) - 1] = 0;
	if (r < arraysize(buff)) {
		return StyleParse(buff);
	} else {
		String str = String(t);
		str.Z[50]  = 0;
		ParseFail("Parse string is too long for StyleParsef: %s...", str.Z);
		XO_DEBUG_ASSERT(false);
		return false;
	}
}
Example #8
0
bool Style::Parse(const char* t, size_t maxLen, Doc* doc) {
// "background: #8f8; width: 100%; height: 100%;"
#define TSTART (t + startv)
#define TLEN (i - startv)
	size_t startk = -1;
	size_t eq     = -1;
	size_t startv = -1;
	int    nerror = 0;
	for (size_t i = 0; true; i++) {
		bool eof = t[i] == 0 || i == maxLen;
		if (t[i] == 32) {
		} else if (t[i] == ':')
			eq = i;
		else if (t[i] == ';' || (eof && startv != -1)) {
			// clang-format off
			bool ok = true;
			if (MATCH(t, startk, eq, "background"))		                { ok = ParseSingleAttrib(TSTART, TLEN, &Color::Parse, CatBackground, *this); }
			else if (MATCH(t, startk, eq, "color"))		                { ok = ParseSingleAttrib(TSTART, TLEN, &Color::Parse, CatColor, *this); }
			else if (MATCH(t, startk, eq, "width"))		                { ok = ParseSingleAttrib(TSTART, TLEN, &Size::Parse, CatWidth, *this); }
			else if (MATCH(t, startk, eq, "height"))		            { ok = ParseSingleAttrib(TSTART, TLEN, &Size::Parse, CatHeight, *this); }
			else if (MATCH(t, startk, eq, "padding"))		            { ok = ParseCompound(TSTART, TLEN, &StyleBox::Parse, CatPadding_Left, *this); }
			else if (MATCH(t, startk, eq, "margin"))		            { ok = ParseCompound(TSTART, TLEN, &StyleBox::Parse, CatMargin_Left, *this); }
			else if (MATCH(t, startk, eq, "display"))		            { ok = ParseSingleAttrib(TSTART, TLEN, &ParseDisplayType, CatDisplay, *this); }
			else if (MATCH(t, startk, eq, "position"))		            { ok = ParseSingleAttrib(TSTART, TLEN, &ParsePositionType, CatPosition, *this); }
			else if (MATCH(t, startk, eq, "border"))		            { ok = ParseDirect(TSTART, TLEN, &ParseBorder, *this); }
			else if (MATCH(t, startk, eq, "border-radius"))		        { ok = ParseSingleAttrib(TSTART, TLEN, &Size::Parse, CatBorderRadius, *this); }
			//else if ( MATCH(t, startk, eq, "left") )                  { ok = ParseSingleAttrib( TSTART, TLEN, &Size::Parse, CatLeft, *this ); }
			//else if ( MATCH(t, startk, eq, "right") )                 { ok = ParseSingleAttrib( TSTART, TLEN, &Size::Parse, CatRight, *this ); }
			//else if ( MATCH(t, startk, eq, "top") )                   { ok = ParseSingleAttrib( TSTART, TLEN, &Size::Parse, CatTop, *this ); }
			//else if ( MATCH(t, startk, eq, "bottom") )                { ok = ParseSingleAttrib( TSTART, TLEN, &Size::Parse, CatBottom, *this ); }
			else if (MATCH(t, startk, eq, "break"))                     { ok = ParseSingleAttrib(TSTART, TLEN, &ParseBreakType, CatBreak, *this); }
			else if (MATCH(t, startk, eq, "canfocus"))                  { ok = ParseBool(TSTART, TLEN, CatCanFocus, *this); }
			else if (MATCH(t, startk, eq, "cursor"))                    { ok = ParseSingleAttrib(TSTART, TLEN, &ParseCursor, CatCursor, *this); }
			else if (MATCH(t, startk, eq, "flow-context"))              { ok = ParseSingleAttrib(TSTART, TLEN, &ParseFlowContext, CatFlowContext, *this); }
			else if (MATCH(t, startk, eq, "flow-axis"))                 { ok = ParseSingleAttrib(TSTART, TLEN, &ParseFlowAxis, CatFlowAxis, *this); }
			else if (MATCH(t, startk, eq, "flow-direction-horizontal")) { ok = ParseSingleAttrib(TSTART, TLEN, &ParseFlowDirection, CatFlowDirection_Horizontal, *this); }
			else if (MATCH(t, startk, eq, "flow-direction-vertical"))   { ok = ParseSingleAttrib(TSTART, TLEN, &ParseFlowDirection, CatFlowDirection_Vertical, *this); }
			else if (MATCH(t, startk, eq, "box-sizing"))                { ok = ParseSingleAttrib(TSTART, TLEN, &ParseBoxSize, CatBoxSizing, *this); }
			else if (MATCH(t, startk, eq, "font-size"))                 { ok = ParseSingleAttrib(TSTART, TLEN, &Size::Parse, CatFontSize, *this); }
			else if (MATCH(t, startk, eq, "font-family"))               { ok = ParseSingleAttrib(TSTART, TLEN, &ParseFontFamily, CatFontFamily, *this); }
			else if (MATCH(t, startk, eq, "text-align-vertical"))       { ok = ParseSingleAttrib(TSTART, TLEN, &ParseTextAlignVertical, CatText_Align_Vertical, *this); }
			else if (MATCH(t, startk, eq, "left"))                      { ok = ParseSingleAttrib(TSTART, TLEN, &ParseHorizontalBinding, CatLeft, *this); }
			else if (MATCH(t, startk, eq, "hcenter"))                   { ok = ParseSingleAttrib(TSTART, TLEN, &ParseHorizontalBinding, CatHCenter, *this); }
			else if (MATCH(t, startk, eq, "right"))                     { ok = ParseSingleAttrib(TSTART, TLEN, &ParseHorizontalBinding, CatRight, *this); }
			else if (MATCH(t, startk, eq, "top"))                       { ok = ParseSingleAttrib(TSTART, TLEN, &ParseVerticalBinding, CatTop, *this); }
			else if (MATCH(t, startk, eq, "vcenter"))                   { ok = ParseSingleAttrib(TSTART, TLEN, &ParseVerticalBinding, CatVCenter, *this); }
			else if (MATCH(t, startk, eq, "bottom"))                    { ok = ParseSingleAttrib(TSTART, TLEN, &ParseVerticalBinding, CatBottom, *this); }
			else if (MATCH(t, startk, eq, "baseline"))                  { ok = ParseSingleAttrib(TSTART, TLEN, &ParseVerticalBinding, CatBaseline, *this); }
			else if (MATCH(t, startk, eq, "bump"))                      { ok = ParseSingleAttrib(TSTART, TLEN, &ParseBump, CatBump, *this); }
			// clang-format on
			else {
				ok = false;
				ParseFail("Parse failed - unknown property: '%.*s'\n", int(eq - startk), t + startk);
			}
			if (!ok)
				nerror++;
			eq     = -1;
			startk = -1;
			startv = -1;
		} else {
			if (startk == -1)
				startk = i;
			else if (startv == -1 && eq != -1)
				startv = i;
		}

		if (eof)
			break;
	}
	return nerror == 0;
#undef TSTART
#undef TLEN
}