Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
CryZe committed Apr 27, 2018
1 parent a8cad2f commit 1ca6076
Show file tree
Hide file tree
Showing 4 changed files with 287 additions and 3 deletions.
40 changes: 40 additions & 0 deletions capi/bind_gen/src/emscripten.rs
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,46 @@ const liveSplitCoreNative = {};"#
}
}

if class_name == "Layout" {
if type_script {
write!(
writer,
"{}",
r#"
static parseOriginalLivesplitString(text: string): Layout | null {
const len = (text.length << 2) + 1;
const buf = emscriptenModule._malloc(len);
try {
const actualLen = emscriptenModule.stringToUTF8(text, buf, len);
return Layout.parseOriginalLivesplit(buf, actualLen);
} finally {
emscriptenModule._free(buf);
}
}"#
)?;
} else {
write!(
writer,
"{}",
r#"
/**
* @param {string} text
* @return {Layout | null}
*/
static parseOriginalLivesplitString(text) {
const len = (text.length << 2) + 1;
const buf = emscriptenModule._malloc(len);
try {
const actualLen = emscriptenModule.stringToUTF8(text, buf, len);
return Layout.parseOriginalLivesplit(buf, actualLen);
} finally {
emscriptenModule._free(buf);
}
}"#
)?;
}
}

if class_name == "Run" {
if type_script {
write!(
Expand Down
245 changes: 243 additions & 2 deletions src/layout/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,80 @@ mod xml_util;
pub use self::xml_util::{Error, Result};

use std::io::BufRead;
use self::xml_util::{end_tag, parse_base, parse_children, text_err};
use self::xml_util::{end_tag, parse_base, parse_children, text, text_err, text_parsed, Tag};
use super::{Component, Layout};
use component::{blank_space, current_comparison, current_pace, delta, detailed_timer, graph,
possible_time_save, previous_segment, separator, splits, sum_of_best, text, timer,
title, total_playtime};
use quick_xml::reader::Reader;
use settings::Color;
use settings::{Color, Gradient};
use time::formatter::Accuracy;

enum GradientKind {
Transparent,
Plain,
Vertical,
Horizontal,
}

struct GradientBuilder {
kind: GradientKind,
first: Color,
second: Color,
}

impl GradientBuilder {
fn new() -> Self {
Self {
kind: GradientKind::Transparent,
first: Color::transparent(),
second: Color::transparent(),
}
}

fn parse_background<'a, R>(
&mut self,
reader: &mut Reader<R>,
tag: Tag<'a>,
) -> Result<Option<Tag<'a>>>
where
R: BufRead,
{
if tag.name() == b"BackgroundColor" {
color(reader, tag.into_buf(), |c| self.first = c)?;
} else if tag.name() == b"BackgroundColor2" {
color(reader, tag.into_buf(), |c| self.second = c)?;
} else if tag.name() == b"BackgroundGradient" {
text_err(reader, tag.into_buf(), |text| {
self.kind = match &*text {
"Plain" => GradientKind::Plain,
"Vertical" => GradientKind::Vertical,
"Horizontal" => GradientKind::Horizontal,
_ => return Err(Error::UnexpectedGradientType),
};
Ok(())
})?;
} else {
return Ok(Some(tag));
}
Ok(None)
}

fn build(self) -> Gradient {
match self.kind {
GradientKind::Transparent => Gradient::Transparent,
GradientKind::Plain => {
if self.first == Color::transparent() {
Gradient::Transparent
} else {
Gradient::Plain(self.first)
}
}
GradientKind::Horizontal => Gradient::Horizontal(self.first, self.second),
GradientKind::Vertical => Gradient::Vertical(self.first, self.second),
}
}
}

fn color<R, F>(reader: &mut Reader<R>, buf: &mut Vec<u8>, f: F) -> Result<()>
where
Expand All @@ -26,6 +93,160 @@ where
})
}

fn parse_bool<R, F>(reader: &mut Reader<R>, buf: &mut Vec<u8>, f: F) -> Result<()>
where
R: BufRead,
F: FnOnce(bool),
{
text_err(reader, buf, |t| match &*t {
"True" => {
f(true);
Ok(())
}
"False" => {
f(false);
Ok(())
}
_ => Err(Error::Bool),
})
}

fn accuracy<R, F>(reader: &mut Reader<R>, buf: &mut Vec<u8>, f: F) -> Result<()>
where
R: BufRead,
F: FnOnce(Accuracy),
{
text_err(reader, buf, |t| {
f(match &*t {
"Tenths" => Accuracy::Tenths,
"Seconds" => Accuracy::Seconds,
"Hundredths" => Accuracy::Hundredths,
_ => return Err(Error::Accuracy),
});
Ok(())
})
}

fn blank_space_settings<R>(
reader: &mut Reader<R>,
buf: &mut Vec<u8>,
component: &mut blank_space::Component,
) -> Result<()>
where
R: BufRead,
{
let settings = component.settings_mut();
let mut background_builder = GradientBuilder::new();

parse_children(reader, buf, |reader, tag| {
if let Some(tag) = background_builder.parse_background(reader, tag)? {
if tag.name() == b"SpaceHeight" {
text_parsed(reader, tag.into_buf(), |h| settings.height = h)
} else {
end_tag(reader, tag.into_buf())
}
} else {
Ok(())
}
})?;

settings.background = background_builder.build();

Ok(())
}

fn current_comparison_settings<R>(
reader: &mut Reader<R>,
buf: &mut Vec<u8>,
component: &mut current_comparison::Component,
) -> Result<()>
where
R: BufRead,
{
let settings = component.settings_mut();
let mut background_builder = GradientBuilder::new();
let (mut override_label, mut override_value) = (false, false);

parse_children(reader, buf, |reader, tag| {
if let Some(tag) = background_builder.parse_background(reader, tag)? {
if tag.name() == b"TextColor" {
color(reader, tag.into_buf(), |c| settings.label_color = Some(c))
} else if tag.name() == b"OverrideTextColor" {
parse_bool(reader, tag.into_buf(), |b| override_label = b)
} else if tag.name() == b"TimeColor" {
color(reader, tag.into_buf(), |c| settings.value_color = Some(c))
} else if tag.name() == b"OverrideTimeColor" {
parse_bool(reader, tag.into_buf(), |b| override_value = b)
} else {
end_tag(reader, tag.into_buf())
}
} else {
Ok(())
}
})?;

if !override_label {
settings.label_color = None;
}
if !override_value {
settings.value_color = None;
}
settings.background = background_builder.build();

Ok(())
}

fn current_pace_settings<R>(
reader: &mut Reader<R>,
buf: &mut Vec<u8>,
component: &mut current_pace::Component,
) -> Result<()>
where
R: BufRead,
{
let settings = component.settings_mut();
let mut background_builder = GradientBuilder::new();
let (mut override_label, mut override_value) = (false, false);

parse_children(reader, buf, |reader, tag| {
if let Some(tag) = background_builder.parse_background(reader, tag)? {
if tag.name() == b"TextColor" {
color(reader, tag.into_buf(), |c| settings.label_color = Some(c))
} else if tag.name() == b"OverrideTextColor" {
parse_bool(reader, tag.into_buf(), |b| override_label = b)
} else if tag.name() == b"TimeColor" {
color(reader, tag.into_buf(), |c| settings.value_color = Some(c))
} else if tag.name() == b"OverrideTimeColor" {
parse_bool(reader, tag.into_buf(), |b| override_value = b)
} else if tag.name() == b"Comparison" {
text(reader, tag.into_buf(), |t| {
settings.comparison_override = if t == "Current Comparison" {
None
} else {
Some(t.into_owned())
};
})
} else if tag.name() == b"Accuracy" {
accuracy(reader, tag.into_buf(), |a| settings.accuracy = a)
} else {
end_tag(reader, tag.into_buf())
}
} else {
Ok(())
}
})?;

if !override_label {
settings.label_color = None;
}
if !override_value {
settings.value_color = None;
}
settings.background = background_builder.build();

Ok(())
}

fn component<R, F>(reader: &mut Reader<R>, buf: &mut Vec<u8>, f: F) -> Result<()>
where
R: BufRead,
Expand Down Expand Up @@ -58,6 +279,26 @@ where
});
Ok(())
})
} else if tag.name() == b"Settings" {
// Assumption: Settings always has to come after the Path.
// Otherwise we need to cache the settings and load them later.
if let Some(ref mut component) = component {
match *component {
Component::BlankSpace(ref mut c) => {
blank_space_settings(reader, tag.into_buf(), c)
}
Component::CurrentComparison(ref mut c) => {
current_comparison_settings(reader, tag.into_buf(), c)
}
Component::CurrentPace(ref mut c) => {
current_pace_settings(reader, tag.into_buf(), c)
}
// _ => unimplemented!(),
_ => end_tag(reader, tag.into_buf()), // ignore other components for now
}
} else {
end_tag(reader, tag.into_buf())
}
} else {
end_tag(reader, tag.into_buf())
}
Expand Down
3 changes: 3 additions & 0 deletions src/layout/parser/xml_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ quick_error! {
ElementNotFound {}
/// The length of a buffer was too large.
LengthOutOfBounds {}
UnexpectedGradientType {}
Bool {}
Accuracy {}
/// Failed to decode a string slice as UTF-8.
Utf8Str(err: str::Utf8Error) {
from()
Expand Down
2 changes: 1 addition & 1 deletion src/settings/color.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ impl From<[f32; 4]> for Color {
impl From<[u8; 4]> for Color {
fn from(rgba: [u8; 4]) -> Self {
Self {
rgba: Rgba::from_pixel(&rgba),
rgba: LinSrgba::from_pixel(&rgba),
}
}
}
Expand Down

0 comments on commit 1ca6076

Please sign in to comment.