示例#1
0
// Returns true if the pseudo-class requirement of a rule is met by a list of an element's pseudo-classes.
bool ElementDefinition::IsPseudoClassRuleApplicable(const StringList& rule_pseudo_classes, const PseudoClassList& element_pseudo_classes) const
{
	for (StringList::size_type i = 0; i < rule_pseudo_classes.size(); ++i)
	{
		if (element_pseudo_classes.find(rule_pseudo_classes[i]) == element_pseudo_classes.end())
			return false;
	}

	return true;
}
示例#2
0
// Iterates over the properties in the definition.
bool ElementDefinition::IterateProperties(int& index, const PseudoClassList& pseudo_classes, PseudoClassList& property_pseudo_classes, String& property_name, const Property*& property) const
{
	if (index < properties.GetNumProperties())
	{
		PropertyMap::const_iterator i = properties.GetProperties().begin();
		for (int count = 0; count < index; ++count)
			++i;

		property_pseudo_classes.clear();
		property_name = (*i).first;
		property = &((*i).second);
		++index;

		return true;
	}

	// Not in the base properties; check for pseudo-class overrides.
	int property_count = properties.GetNumProperties();
	for (PseudoClassPropertyDictionary::const_iterator i = pseudo_class_properties.begin(); i != pseudo_class_properties.end(); ++i)
	{
		// Iterate over each pseudo-class set that has a definition for this property; if we find one that matches our
		// pseudo-class, increment our index counter and either return that property (if we hit the requested index) or
		// continue looking if we're still below it.
		for (size_t j = 0; j < (*i).second.size(); ++j)
		{
			if (IsPseudoClassRuleApplicable((*i).second[j].first, pseudo_classes))
			{
				property_count++;
				if (property_count > index)
				{
					// Copy the list of pseudo-classes.
					property_pseudo_classes.clear();
					for (size_t k = 0; k < (*i).second[j].first.size(); ++k)
						property_pseudo_classes.insert((*i).second[j].first[k]);

					property_name = (*i).first;
					property = &((*i).second[j].second);
					++index;

					return true;
				}
				else
				{
					break;
				}
			}
		}
	}

	return false;
}
示例#3
0
// Returns the list of properties this element definition has explicit definitions for involving the given
// pseudo-class.
void ElementDefinition::GetDefinedProperties(PropertyNameList& property_names, const PseudoClassList& pseudo_classes, const String& pseudo_class) const
{
	for (PseudoClassPropertyDictionary::const_iterator i = pseudo_class_properties.begin(); i != pseudo_class_properties.end(); ++i)
	{
		// If this property has already been found, don't bother checking for it again.
		if (property_names.find((*i).first) != property_names.end())
			continue;

		const PseudoClassPropertyList& property_list = (*i).second;

		bool property_defined = false;
		for (size_t j = 0; j < property_list.size(); ++j)
		{
			bool rule_valid = true;
			bool found_toggled_pseudo_class = false;

			const StringList& rule_pseudo_classes = property_list[j].first;
			for (size_t j = 0; j < rule_pseudo_classes.size(); ++j)
			{
				if (rule_pseudo_classes[j] == pseudo_class)
				{
					found_toggled_pseudo_class = true;
					continue;
				}

				if (pseudo_classes.find(rule_pseudo_classes[j]) == pseudo_classes.end())
				{			
					rule_valid = false;
					break;
				}
			}

			if (rule_valid &&
				found_toggled_pseudo_class)
			{
				property_defined = true;
				break;
			}
		}

		if (property_defined)
			property_names.insert((*i).first);
	}
}
// Iterates over the properties defined on the element.
bool ElementStyle::IterateProperties(int& index, PseudoClassList& property_pseudo_classes, String& name, const Property*& property)
{
	// First check for locally defined properties.
	if (local_properties != NULL)
	{
		if (index < local_properties->GetNumProperties())
		{
			PropertyMap::const_iterator i = local_properties->GetProperties().begin();
			for (int count = 0; count < index; ++count)
				++i;

			name = (*i).first;
			property = &((*i).second);
			property_pseudo_classes.clear();
			++index;

			return true;
		}
	}

	const ElementDefinition* definition = GetDefinition();
	if (definition != NULL)
	{
		int index_offset = 0;
		if (local_properties != NULL)
			index_offset = local_properties->GetNumProperties();

		// Offset the index to be relative to the definition before we start indexing. When we do get a property back,
		// check that it hasn't been overridden by the element's local properties; if so, continue on to the next one.
		index -= index_offset;
		while (definition->IterateProperties(index, pseudo_classes, property_pseudo_classes, name, property))
		{
			if (local_properties == NULL ||
				local_properties->GetProperty(name) == NULL)
			{
				index += index_offset;
				return true;
			}
		}

		return false;
	}

	return false;
}
示例#5
0
// Adds to a list the names of this node's pseudo-classes which are deemed volatile.
bool StyleSheetNode::GetVolatilePseudoClasses(PseudoClassList& volatile_pseudo_classes) const
{
	if (type == PSEUDO_CLASS)
	{
		bool self_volatile = !children[TAG].empty();

		for (NodeMap::const_iterator i = children[PSEUDO_CLASS].begin(); i != children[PSEUDO_CLASS].end(); ++i)
			self_volatile = (*i).second->GetVolatilePseudoClasses(volatile_pseudo_classes) | self_volatile;

		if (self_volatile)
			volatile_pseudo_classes.insert(name);

		return self_volatile;
	}
	else
	{
		for (NodeMap::const_iterator i = children[PSEUDO_CLASS].begin(); i != children[PSEUDO_CLASS].end(); ++i)
			(*i).second->GetVolatilePseudoClasses(volatile_pseudo_classes);
	}

	return false;
}
示例#6
0
// Initialises the element definition from a list of style sheet nodes.
void ElementDefinition::Initialise(const std::vector< const StyleSheetNode* >& style_sheet_nodes, const PseudoClassList& volatile_pseudo_classes, bool _structurally_volatile)
{
	// Set the volatile structure flag.
	structurally_volatile = _structurally_volatile;

	// Mark all the volatile pseudo-classes as structurally volatile.
	for (PseudoClassList::const_iterator i = volatile_pseudo_classes.begin(); i != volatile_pseudo_classes.end(); ++i)
		pseudo_class_volatility[*i] = STRUCTURE_VOLATILE;


	// Merge the default (non-pseudo-class) properties.
	for (size_t i = 0; i < style_sheet_nodes.size(); ++i)
		properties.Merge(style_sheet_nodes[i]->GetProperties());


	// Merge the pseudo-class properties.
	PseudoClassPropertyMap merged_pseudo_class_properties;
	for (size_t i = 0; i < style_sheet_nodes.size(); ++i)
	{
		// Merge all the pseudo-classes.
		PseudoClassPropertyMap node_properties;
		style_sheet_nodes[i]->GetPseudoClassProperties(node_properties);
		for (PseudoClassPropertyMap::iterator j = node_properties.begin(); j != node_properties.end(); ++j)
		{
			// Merge the property maps into one uber-map; for the decorators.
			PseudoClassPropertyMap::iterator k = merged_pseudo_class_properties.find((*j).first);
			if (k == merged_pseudo_class_properties.end())
				merged_pseudo_class_properties[(*j).first] = (*j).second;
			else
				(*k).second.Merge((*j).second);

			// Search through all entries in this dictionary; we'll insert each one into our optimised list of
			// pseudo-class properties.
			for (PropertyMap::const_iterator k = (*j).second.GetProperties().begin(); k != (*j).second.GetProperties().end(); ++k)
			{
				const String& property_name = (*k).first;
				const Property& property = (*k).second;

				// Skip this property if its specificity is lower than the base property's, as in
				// this case it will never be used.
				const Property* default_property = properties.GetProperty(property_name);
				if (default_property != NULL &&
					default_property->specificity >= property.specificity)
					continue;

				PseudoClassPropertyDictionary::iterator l = pseudo_class_properties.find(property_name);
				if (l == pseudo_class_properties.end())
					pseudo_class_properties[property_name] = PseudoClassPropertyList(1, PseudoClassProperty((*j).first, property));
				else
				{
					// Find the location to insert this entry in the map, based on property priorities.
					int index = 0;
					while (index < (int) (*l).second.size() &&
						   (*l).second[index].second.specificity > property.specificity)
						index++;

					(*l).second.insert((*l).second.begin() + index, PseudoClassProperty((*j).first, property));
				}
			}
		}
	}

	InstanceDecorators(merged_pseudo_class_properties);
	InstanceFontEffects(merged_pseudo_class_properties);
}