Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Media queries #169

Merged
merged 34 commits into from
Feb 7, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
141af44
defined media features and refactor of stylesheet
Dakror Jan 21, 2021
64ce79f
media query list class
Dakror Jan 21, 2021
585effb
media query list class
Dakror Jan 21, 2021
42db20e
api definition change
Dakror Jan 22, 2021
5f2ae95
restructure to restore old version of stylesheet and move stylesheet …
Dakror Jan 22, 2021
31da349
parser setup
Dakror Jan 23, 2021
7f154de
tests are passing!
Dakror Jan 24, 2021
295b617
Merge branch 'master' of https://github.com/mikke89/RmlUi into media-…
Dakror Jan 24, 2021
bb8169b
parser and unit test
Dakror Jan 24, 2021
5083d46
fix unit test
Dakror Jan 24, 2021
5a7ab55
new properties and propertydefinition flags
Dakror Jan 25, 2021
9b5765f
parse properties using parser
Dakror Jan 25, 2021
6381a6a
Revert PropertyFlags as they are too complicated
Dakror Jan 26, 2021
5dbfa68
media query parser and more test cases
Dakror Jan 26, 2021
3f191a7
Dirty stylesheet container
Dakror Jan 26, 2021
9d1f559
Fix build errors without pch
Dakror Jan 26, 2021
7e88e96
fix more compile errors
Dakror Jan 26, 2021
dd1a749
rework the dirtying of the stylesheet
Dakror Jan 26, 2021
8134fba
Merge branch 'master' of https://github.com/mikke89/RmlUi into media-…
Dakror Jan 26, 2021
6eaac20
First sweep of easy fixes
Dakror Feb 1, 2021
a104282
Merge branch 'master' of https://github.com/mikke89/RmlUi into media-…
Dakror Feb 1, 2021
d11bed1
include parser keeps coming back... im haunted
Dakror Feb 1, 2021
83372e7
more small fixes
Dakror Feb 1, 2021
47f0bfa
media query id
Dakror Feb 1, 2021
f252bdb
media block struct
Dakror Feb 1, 2021
072a61d
stylesheet types
Dakror Feb 1, 2021
44d6454
x unit
Dakror Feb 1, 2021
12f31fc
clang fixes
Dakror Feb 1, 2021
98bcc50
fix specificity offset missing
Dakror Feb 2, 2021
91a6db4
fix unit test
Dakror Feb 2, 2021
c0da560
x unit
Dakror Feb 2, 2021
08f77c6
stylesheet private constructor
Dakror Feb 6, 2021
08fc6ad
fix pch
Dakror Feb 6, 2021
57883eb
few more fixes
Dakror Feb 7, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
media query parser and more test cases
  • Loading branch information
Dakror committed Jan 26, 2021
commit 5dbfa68c94c6826742279967a37e0e9b71606429
68 changes: 55 additions & 13 deletions Source/Core/StyleSheetParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,54 @@ class SpritesheetPropertyParser final : public AbstractPropertyParser {

static UniquePtr<SpritesheetPropertyParser> spritesheet_property_parser;

/*
* Media queries need a special parser because they have unique properties that
* aren't admissible in other property declaration contexts and the syntax of
*/
class MediaQueryPropertyParser final : public AbstractPropertyParser {
private:
// The dictionary to store the properties in.
PropertyDictionary* properties;

PropertySpecification specification;

public:
MediaQueryPropertyParser() : specification(14, 0)
{
specification.RegisterProperty("width", "", false, false, PropertyId::Width).AddParser("pixels");
specification.RegisterProperty("min-width", "", false, false, PropertyId::MinWidth).AddParser("pixels");
specification.RegisterProperty("max-width", "", false, false, PropertyId::MaxWidth).AddParser("pixels");

specification.RegisterProperty("height", "", false, false, PropertyId::Height).AddParser("pixels");
specification.RegisterProperty("min-height", "", false, false, PropertyId::MinHeight).AddParser("pixels");
specification.RegisterProperty("max-height", "", false, false, PropertyId::MaxHeight).AddParser("pixels");
Dakror marked this conversation as resolved.
Show resolved Hide resolved

specification.RegisterProperty("aspect-ratio", "", false, false, PropertyId::AspectRatio).AddParser("aspect_ratio");
specification.RegisterProperty("min-aspect-ratio", "", false, false, PropertyId::MinAspectRatio).AddParser("aspect_ratio");
specification.RegisterProperty("max-aspect-ratio", "", false, false, PropertyId::MaxAspectRatio).AddParser("aspect_ratio");

specification.RegisterProperty("resolution", "", false, false, PropertyId::Resolution).AddParser("resolution");
specification.RegisterProperty("min-resolution", "", false, false, PropertyId::MinResolution).AddParser("resolution");
specification.RegisterProperty("max-resolution", "", false, false, PropertyId::MaxResolution).AddParser("resolution");

specification.RegisterProperty("orientation", "", false, false, PropertyId::Orientation).AddParser("keyword", "landscape, portrait");
}

void SetTargetProperties(PropertyDictionary* _properties)
{
properties = _properties;
}

bool Parse(const String& name, const String& value) override
{
RMLUI_ASSERT(properties);
return specification.ParsePropertyDeclaration(*properties, name, value);
}
};


static UniquePtr<MediaQueryPropertyParser> media_query_property_parser;


StyleSheetParser::StyleSheetParser()
{
Expand All @@ -156,6 +204,7 @@ StyleSheetParser::~StyleSheetParser()
void StyleSheetParser::Initialise()
{
spritesheet_property_parser = MakeUnique<SpritesheetPropertyParser>();
media_query_property_parser = MakeUnique<MediaQueryPropertyParser>();
}

void StyleSheetParser::Shutdown()
Dakror marked this conversation as resolved.
Show resolved Hide resolved
Expand Down Expand Up @@ -338,8 +387,10 @@ bool StyleSheetParser::ParseDecoratorBlock(const String& at_name, DecoratorSpeci
return true;
}

bool StyleSheetParser::ParseMediaFeatureMap(AbstractPropertyParser& parser, const String & rules)
bool StyleSheetParser::ParseMediaFeatureMap(PropertyDictionary& properties, const String & rules)
{
media_query_property_parser->SetTargetProperties(&properties);

enum ParseState { Global, Name, Value };
ParseState state = Name;

Expand Down Expand Up @@ -389,16 +440,8 @@ bool StyleSheetParser::ParseMediaFeatureMap(AbstractPropertyParser& parser, cons

current_string = StringUtilities::StripWhitespace(StringUtilities::ToLower(current_string));
Dakror marked this conversation as resolved.
Show resolved Hide resolved

Log::Message(Log::LT_DEBUG, "%s:%s", name.c_str(), current_string.c_str());

if (!IsValidIdentifier(current_string))
{
Log::Message(Log::LT_WARNING, "Malformed property value '%s' in @media query list at %s:%d.", current_string.c_str(), stream_file_name.c_str(), line_number);
return false;
}

if(!parser.Parse(name, current_string))
Log::Message(Log::LT_WARNING, "Syntax error parsing property declaration '%s: %s;' in %s: %d.", name.c_str(), current_string.c_str(), stream_file_name.c_str(), line_number);
if(!media_query_property_parser->Parse(name, current_string))
Log::Message(Log::LT_WARNING, "Syntax error parsing media-query property declaration '%s: %s;' in %s: %d.", name.c_str(), current_string.c_str(), stream_file_name.c_str(), line_number);

current_string.clear();
state = Global;
Expand Down Expand Up @@ -579,8 +622,7 @@ int StyleSheetParser::Parse(MediaBlockListRaw& style_sheets, Stream* _stream, in

// parse media query list into block
PropertyDictionary feature_map;
PropertySpecificationParser parser(feature_map, StyleSheetSpecification::GetPropertySpecification());
ParseMediaFeatureMap(parser, pre_token_str.substr(pre_token_str.find(' ') + 1));
ParseMediaFeatureMap(feature_map, pre_token_str.substr(pre_token_str.find(' ') + 1));
current_block = {feature_map, MakeUnique<StyleSheet>()};

inside_media_block = true;
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/StyleSheetParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ class StyleSheetParser
bool ParseDecoratorBlock(const String& at_name, DecoratorSpecificationMap& decorator_map, const StyleSheet& style_sheet, const SharedPtr<const PropertySource>& source);

// Attempts to parse the properties of a @media query
bool ParseMediaFeatureMap(AbstractPropertyParser& parser, const String& rules);
bool ParseMediaFeatureMap(PropertyDictionary& properties, const String& rules);

// Attempts to find one of the given character tokens in the active stream
// If it's found, buffer is filled with all content up until the token
Expand Down
3 changes: 2 additions & 1 deletion Source/Core/StyleSheetSpecification.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ struct DefaultStyleSheetParsers {
PropertyParserTransform transform = PropertyParserTransform();
PropertyParserAspectRatio aspect_ratio = PropertyParserAspectRatio();
PropertyParserNumber resolution = PropertyParserNumber(Property::DPI);
PropertyParserNumber pixels = PropertyParserNumber(Property::PX);
Dakror marked this conversation as resolved.
Show resolved Hide resolved
};

StyleSheetSpecification::StyleSheetSpecification() :
Expand Down Expand Up @@ -252,6 +253,7 @@ void StyleSheetSpecification::RegisterDefaultParsers()
RegisterParser("transform", &default_parsers->transform);
RegisterParser("aspect_ratio", &default_parsers->aspect_ratio);
RegisterParser("resolution", &default_parsers->resolution);
RegisterParser("pixels", &default_parsers->pixels);
}


Expand Down Expand Up @@ -416,7 +418,6 @@ void StyleSheetSpecification::RegisterDefaultProperties()
// Rare properties (not added to computed values)
RegisterProperty(PropertyId::FillImage, "fill-image", "", false, false).AddParser("string");

RMLUI_ASSERTMSG(instance->properties.property_map->AssertAllInserted(PropertyId::NumDefinedIds), "Missing specification for one or more Property IDs.");
Dakror marked this conversation as resolved.
Show resolved Hide resolved
RMLUI_ASSERTMSG(instance->properties.shorthand_map->AssertAllInserted(ShorthandId::NumDefinedIds), "Missing specification for one or more Shorthand IDs.");
}

Expand Down
155 changes: 151 additions & 4 deletions Tests/Source/UnitTests/MediaQueries.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,106 @@ static const String document_media_query1_rml = R"(
bottom: 0;
}

div {
height: 48px;
width: 48px;
}

@media (min-width: 640px) {
div {
height: 32px;
width: 32px;
}
}

@media (max-width: 639px) {
div {
background: #666;
height: 64px;
width: 64px;
}
}
</style>
</head>

<body>
<div/>
</body>
</rml>
)";

static const String document_media_query2_rml = R"(
<rml>
<head>
<title>Test</title>
<link type="text/rcss" href="/assets/rml.rcss"/>
<style>
body {
left: 0;
top: 0;
right: 0;
bottom: 0;
}

div {
height: 48px;
width: 48px;
}

@media (orientation: landscape) {
div {
height: 32px;
width: 32px;
}
}

@media (min-width: 640px) {
@media (max-aspect-ratio: 3/4) {
div {
height: 64px;
width: 64px;
}
}

@media (min-resolution: 90dpi) {
div {
height: 128px;
}
}
</style>
</head>

<body>
<div/>
</body>
</rml>
)";

static const String document_media_query3_rml = R"(
<rml>
<head>
<title>Test</title>
<link type="text/rcss" href="/assets/rml.rcss"/>
<style>
body {
left: 0;
top: 0;
right: 0;
bottom: 0;
}

div {
height: 48px;
width: 48px;
}

@media (orientation: landscape) and (min-width: 640px) {
div {
height: 32px;
width: 32px;
}
}

@media (max-aspect-ratio: 4/3) {
div {
background: #333;
height: 64px;
width: 64px;
}
Expand Down Expand Up @@ -93,7 +182,65 @@ TEST_CASE("mediaqueries.basic")
document->GetElementsByTagName(elems, "div");
CHECK(elems.size() == 1);

CHECK(elems[0]->GetBox() == Box(Vector2f(64.0f, 64.0f)));
CHECK(elems[0]->GetBox() == Box(Vector2f(32.0f, 32.0f)));

document->Close();

TestsShell::ShutdownShell();
}

TEST_CASE("mediaqueries.custom_properties")
{
Context* context = TestsShell::GetContext();
REQUIRE(context);

context->SetDensityIndependentPixelRatio(90.0f);

// There should be no warnings loading this document. There should be one div of 32px width & height
ElementDocument* document = context->LoadDocumentFromMemory(document_media_query2_rml, "assets/");
REQUIRE(document);
document->Show();

context->Update();
context->Render();

TestsShell::RenderLoop();

// Shell default window dimensions are 1500, 800

ElementList elems;
document->GetElementsByTagName(elems, "div");
CHECK(elems.size() == 1);

CHECK(elems[0]->GetBox() == Box(Vector2f(32.0f, 128.0f)));

document->Close();

TestsShell::ShutdownShell();
}

TEST_CASE("mediaqueries.composite")
{
Context* context = TestsShell::GetContext();
REQUIRE(context);

// There should be no warnings loading this document. There should be one div of 32px width & height
ElementDocument* document = context->LoadDocumentFromMemory(document_media_query3_rml, "assets/");
REQUIRE(document);
document->Show();

context->Update();
context->Render();

TestsShell::RenderLoop();

// Shell default window dimensions are 1500, 800

ElementList elems;
document->GetElementsByTagName(elems, "div");
CHECK(elems.size() == 1);

CHECK(elems[0]->GetBox() == Box(Vector2f(32.0f, 32.0f)));

document->Close();

Expand Down