/*
* This source file is part of RmlUi, the HTML/CSS Interface Middleware
*
* For the latest information, see http://github.com/mikke89/RmlUi
*
* Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
* Copyright (c) 2019 The RmlUi Team, and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#include "../../Include/RmlUi/Core/PropertyDictionary.h"
#include "../../Include/RmlUi/Core/StyleSheetContainer.h"
#include "../../Include/RmlUi/Core/StyleSheet.h"
#include "ComputeProperty.h"
#include "StyleSheetParser.h"
#include "Utilities.h"
namespace Rml {
StyleSheetContainer::StyleSheetContainer()
{
}
StyleSheetContainer::~StyleSheetContainer()
{
}
bool StyleSheetContainer::LoadStyleSheetContainer(Stream* stream, int begin_line_number)
{
StyleSheetParser parser;
int rule_count = parser.Parse(media_blocks, stream, begin_line_number);
return rule_count >= 0;
}
StyleSheet* StyleSheetContainer::GetCompiledStyleSheet(float dp_ratio, Vector2f vp_dimensions)
{
if(compiled_style_sheet && vp_dimensions == current_dimensions && dp_ratio == current_density_ratio)
return compiled_style_sheet.get();
UniquePtr new_sheet = UniquePtr(new StyleSheet());
float font_size = DefaultComputedValues.font_size;
for(auto const& media_block : media_blocks)
{
bool all_match = true;
for(auto const& property : media_block.properties.GetProperties())
{
switch(static_cast(property.first))
{
case MediaQueryId::Width:
if(vp_dimensions.x != ComputeLength(&property.second, font_size, font_size, dp_ratio, vp_dimensions))
all_match = false;
break;
case MediaQueryId::MinWidth:
if(vp_dimensions.x < ComputeLength(&property.second, font_size, font_size, dp_ratio, vp_dimensions))
all_match = false;
break;
case MediaQueryId::MaxWidth:
if(vp_dimensions.x > ComputeLength(&property.second, font_size, font_size, dp_ratio, vp_dimensions))
all_match = false;
break;
case MediaQueryId::Height:
if(vp_dimensions.y != ComputeLength(&property.second, font_size, font_size, dp_ratio, vp_dimensions))
all_match = false;
break;
case MediaQueryId::MinHeight:
if(vp_dimensions.y < ComputeLength(&property.second, font_size, font_size, dp_ratio, vp_dimensions))
all_match = false;
break;
case MediaQueryId::MaxHeight:
if(vp_dimensions.y > ComputeLength(&property.second, font_size, font_size, dp_ratio, vp_dimensions))
all_match = false;
break;
case MediaQueryId::AspectRatio:
if((vp_dimensions.x / vp_dimensions.y) != property.second.Get())
all_match = false;
break;
case MediaQueryId::MinAspectRatio:
if((vp_dimensions.x / vp_dimensions.y) < property.second.Get())
all_match = false;
break;
case MediaQueryId::MaxAspectRatio:
if((vp_dimensions.x / vp_dimensions.y) > property.second.Get())
all_match = false;
break;
case MediaQueryId::Resolution:
if(dp_ratio != property.second.Get())
all_match = false;
break;
case MediaQueryId::MinResolution:
if(dp_ratio < property.second.Get())
all_match = false;
break;
case MediaQueryId::MaxResolution:
if(dp_ratio > property.second.Get())
all_match = false;
break;
case MediaQueryId::Orientation:
// Landscape (x > y) = 0
// Portrait (x <= y) = 1
if((vp_dimensions.x <= vp_dimensions.y) != property.second.Get())
all_match = false;
break;
// Invalid properties
case MediaQueryId::Invalid:
case MediaQueryId::NumDefinedIds:
case MediaQueryId::MaxNumIds:
break;
}
if(!all_match)
break;
}
if(all_match)
{
new_sheet = new_sheet->CombineStyleSheet(*media_block.stylesheet);
}
}
new_sheet->BuildNodeIndex();
new_sheet->OptimizeNodeProperties();
compiled_style_sheet = std::move(new_sheet);
current_dimensions = vp_dimensions;
current_density_ratio = dp_ratio;
return compiled_style_sheet.get();
}
/// Combines this style sheet container with another one, producing a new sheet container.
SharedPtr StyleSheetContainer::CombineStyleSheetContainer(const StyleSheetContainer& container) const
{
SharedPtr new_sheet = MakeShared();
for(auto const& pair : media_blocks)
{
PropertyDictionary dict;
dict.Import(pair.properties);
new_sheet->media_blocks.emplace_back(dict, pair.stylesheet->Clone());
}
for(auto const& pair : container.media_blocks)
{
bool block_found = false;
for(auto& media_block : new_sheet->media_blocks)
{
if(pair.properties.GetProperties() == media_block.properties.GetProperties())
{
media_block.stylesheet = media_block.stylesheet->CombineStyleSheet(*pair.stylesheet);
block_found = true;
break;
}
}
if (!block_found)
{
PropertyDictionary dict;
dict.Import(pair.properties);
new_sheet->media_blocks.emplace_back(dict, pair.stylesheet->Clone());
}
}
return new_sheet;
}
} // namespace Rml