Update current version of litehtml. Fix a crash when document contains no fonts
[claws.git] / src / plugins / litehtml_viewer / litehtml / media_query.cpp
index 6cc66daf13d138ecaed9a6956a32dc52bd8a1f8d..41ff39ede98d5bf407c0c725d212c22d38f14d25 100644 (file)
-#include "html.h"\r
-#include "media_query.h"\r
-#include "document.h"\r
-\r
-\r
-litehtml::media_query::media_query()\r
-{\r
-       m_media_type    = media_type_all;\r
-       m_not                   = false;\r
-}\r
-\r
-litehtml::media_query::media_query( const media_query& val )\r
-{\r
-       m_not                   = val.m_not;\r
-       m_expressions   = val.m_expressions;\r
-       m_media_type    = val.m_media_type;\r
-}\r
-\r
-litehtml::media_query::ptr litehtml::media_query::create_from_string(const tstring& str, const std::shared_ptr<document>& doc)\r
-{\r
-       media_query::ptr query = std::make_shared<media_query>();\r
-\r
-       string_vector tokens;\r
-       split_string(str, tokens, _t(" \t\r\n"), _t(""), _t("("));\r
-\r
-       for(string_vector::iterator tok = tokens.begin(); tok != tokens.end(); tok++)\r
-       {\r
-               if((*tok) == _t("not"))\r
-               {\r
-                       query->m_not = true;\r
-               } else if(tok->at(0) == _t('('))\r
-               {\r
-                       tok->erase(0, 1);\r
-                       if(tok->at(tok->length() - 1) == _t(')'))\r
-                       {\r
-                               tok->erase(tok->length() - 1, 1);\r
-                       }\r
-                       media_query_expression expr;\r
-                       string_vector expr_tokens;\r
-                       split_string((*tok), expr_tokens, _t(":"));\r
-                       if(!expr_tokens.empty())\r
-                       {\r
-                               trim(expr_tokens[0]);\r
-                               expr.feature = (media_feature) value_index(expr_tokens[0], media_feature_strings, media_feature_none);\r
-                               if(expr.feature != media_feature_none)\r
-                               {\r
-                                       if(expr_tokens.size() == 1)\r
-                                       {\r
-                                               expr.check_as_bool = true;\r
-                                       } else\r
-                                       {\r
-                                               trim(expr_tokens[1]);\r
-                                               expr.check_as_bool = false;\r
-                                               if(expr.feature == media_feature_orientation)\r
-                                               {\r
-                                                       expr.val = value_index(expr_tokens[1], media_orientation_strings, media_orientation_landscape);\r
-                                               } else\r
-                                               {\r
-                                                       tstring::size_type slash_pos = expr_tokens[1].find(_t('/'));\r
-                                                       if( slash_pos != tstring::npos )\r
-                                                       {\r
-                                                               tstring val1 = expr_tokens[1].substr(0, slash_pos);\r
-                                                               tstring val2 = expr_tokens[1].substr(slash_pos + 1);\r
-                                                               trim(val1);\r
-                                                               trim(val2);\r
-                                                               expr.val = t_atoi(val1.c_str());\r
-                                                               expr.val2 = t_atoi(val2.c_str());\r
-                                                       } else\r
-                                                       {\r
-                                                               css_length length;\r
-                                                               length.fromString(expr_tokens[1]);\r
-                                                               if(length.units() == css_units_dpcm)\r
-                                                               {\r
-                                                                       expr.val = (int) (length.val() * 2.54);\r
-                                                               } else if(length.units() == css_units_dpi)\r
-                                                               {\r
-                                                                       expr.val = (int) (length.val() * 2.54);\r
-                                                               } else\r
-                                                               {\r
-                                                                       if(doc)\r
-                                                                       {\r
-                                                                               doc->cvt_units(length, doc->container()->get_default_font_size());\r
-                                                                       }\r
-                                                                       expr.val = (int) length.val();\r
-                                                               }\r
-                                                       }\r
-                                               }\r
-                                       }\r
-                                       query->m_expressions.push_back(expr);\r
-                               }\r
-                       }\r
-               } else\r
-               {\r
-                       query->m_media_type = (media_type) value_index((*tok), media_type_strings, media_type_all);\r
-\r
-               }\r
-       }\r
-\r
-       return query;\r
-}\r
-\r
-bool litehtml::media_query::check( const media_features& features ) const\r
-{\r
-       bool res = false;\r
-       if(m_media_type == media_type_all || m_media_type == features.type)\r
-       {\r
-               res = true;\r
-               for(media_query_expression::vector::const_iterator expr = m_expressions.begin(); expr != m_expressions.end() && res; expr++)\r
-               {\r
-                       if(!expr->check(features))\r
-                       {\r
-                               res = false;\r
-                       }\r
-               }\r
-       }\r
-\r
-       if(m_not)\r
-       {\r
-               res = !res;\r
-       }\r
-\r
-       return res;\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////////\r
-\r
-litehtml::media_query_list::ptr litehtml::media_query_list::create_from_string(const tstring& str, const std::shared_ptr<document>& doc)\r
-{\r
-       media_query_list::ptr list = std::make_shared<media_query_list>();\r
-\r
-       string_vector tokens;\r
-       split_string(str, tokens, _t(","));\r
-\r
-       for(string_vector::iterator tok = tokens.begin(); tok != tokens.end(); tok++)\r
-       {\r
-               trim(*tok);\r
-               lcase(*tok);\r
-\r
-               litehtml::media_query::ptr query = media_query::create_from_string(*tok, doc);\r
-               if(query)\r
-               {\r
-                       list->m_queries.push_back(query);\r
-               }\r
-       }\r
-       if(list->m_queries.empty())\r
-       {\r
-               list = 0;\r
-       }\r
-\r
-       return list;\r
-}\r
-\r
-bool litehtml::media_query_list::apply_media_features( const media_features& features )\r
-{\r
-       bool apply = false;\r
-       \r
-       for(media_query::vector::iterator iter = m_queries.begin(); iter != m_queries.end() && !apply; iter++)\r
-       {\r
-               if((*iter)->check(features))\r
-               {\r
-                       apply = true;\r
-               }\r
-       }\r
-\r
-       bool ret = (apply != m_is_used);\r
-       m_is_used = apply;\r
-       return ret;\r
-}\r
-\r
-bool litehtml::media_query_expression::check( const media_features& features ) const\r
-{\r
-       switch(feature)\r
-       {\r
-       case media_feature_width:\r
-               if(check_as_bool)\r
-               {\r
-                       return (features.width != 0);\r
-               } else if(features.width == val)\r
-               {\r
-                       return true;\r
-               }\r
-               break;\r
-       case media_feature_min_width:\r
-               if(features.width >= val)\r
-               {\r
-                       return true;\r
-               }\r
-               break;\r
-       case media_feature_max_width:\r
-               if(features.width <= val)\r
-               {\r
-                       return true;\r
-               }\r
-               break;\r
-       case media_feature_height:\r
-               if(check_as_bool)\r
-               {\r
-                       return (features.height != 0);\r
-               } else if(features.height == val)\r
-               {\r
-                       return true;\r
-               }\r
-               break;\r
-       case media_feature_min_height:\r
-               if(features.height >= val)\r
-               {\r
-                       return true;\r
-               }\r
-               break;\r
-       case media_feature_max_height:\r
-               if(features.height <= val)\r
-               {\r
-                       return true;\r
-               }\r
-               break;\r
-\r
-       case media_feature_device_width:\r
-               if(check_as_bool)\r
-               {\r
-                       return (features.device_width != 0);\r
-               } else if(features.device_width == val)\r
-               {\r
-                       return true;\r
-               }\r
-               break;\r
-       case media_feature_min_device_width:\r
-               if(features.device_width >= val)\r
-               {\r
-                       return true;\r
-               }\r
-               break;\r
-       case media_feature_max_device_width:\r
-               if(features.device_width <= val)\r
-               {\r
-                       return true;\r
-               }\r
-               break;\r
-       case media_feature_device_height:\r
-               if(check_as_bool)\r
-               {\r
-                       return (features.device_height != 0);\r
-               } else if(features.device_height == val)\r
-               {\r
-                       return true;\r
-               }\r
-               break;\r
-       case media_feature_min_device_height:\r
-               if(features.device_height <= val)\r
-               {\r
-                       return true;\r
-               }\r
-               break;\r
-       case media_feature_max_device_height:\r
-               if(features.device_height <= val)\r
-               {\r
-                       return true;\r
-               }\r
-               break;\r
-\r
-       case media_feature_orientation:\r
-               if(features.height >= features.width)\r
-               {\r
-                       if(val == media_orientation_portrait)\r
-                       {\r
-                               return true;\r
-                       }\r
-               } else\r
-               {\r
-                       if(val == media_orientation_landscape)\r
-                       {\r
-                               return true;\r
-                       }\r
-               }\r
-               break;\r
-       case media_feature_aspect_ratio:\r
-               if(features.height && val2)\r
-               {\r
-                       int ratio_this = round_d( (double) val / (double) val2 * 100 );\r
-                       int ratio_feat = round_d( (double) features.width / (double) features.height * 100.0 );\r
-                       if(ratio_this == ratio_feat)\r
-                       {\r
-                               return true;\r
-                       }\r
-               }\r
-               break;\r
-       case media_feature_min_aspect_ratio:\r
-               if(features.height && val2)\r
-               {\r
-                       int ratio_this = round_d( (double) val / (double) val2 * 100 );\r
-                       int ratio_feat = round_d( (double) features.width / (double) features.height * 100.0 );\r
-                       if(ratio_feat >= ratio_this)\r
-                       {\r
-                               return true;\r
-                       }\r
-               }\r
-               break;\r
-       case media_feature_max_aspect_ratio:\r
-               if(features.height && val2)\r
-               {\r
-                       int ratio_this = round_d( (double) val / (double) val2 * 100 );\r
-                       int ratio_feat = round_d( (double) features.width / (double) features.height * 100.0 );\r
-                       if(ratio_feat <= ratio_this)\r
-                       {\r
-                               return true;\r
-                       }\r
-               }\r
-               break;\r
-\r
-       case media_feature_device_aspect_ratio:\r
-               if(features.device_height && val2)\r
-               {\r
-                       int ratio_this = round_d( (double) val / (double) val2 * 100 );\r
-                       int ratio_feat = round_d( (double) features.device_width / (double) features.device_height * 100.0 );\r
-                       if(ratio_feat == ratio_this)\r
-                       {\r
-                               return true;\r
-                       }\r
-               }\r
-               break;\r
-       case media_feature_min_device_aspect_ratio:\r
-               if(features.device_height && val2)\r
-               {\r
-                       int ratio_this = round_d( (double) val / (double) val2 * 100 );\r
-                       int ratio_feat = round_d( (double) features.device_width / (double) features.device_height * 100.0 );\r
-                       if(ratio_feat >= ratio_this)\r
-                       {\r
-                               return true;\r
-                       }\r
-               }\r
-               break;\r
-       case media_feature_max_device_aspect_ratio:\r
-               if(features.device_height && val2)\r
-               {\r
-                       int ratio_this = round_d( (double) val / (double) val2 * 100 );\r
-                       int ratio_feat = round_d( (double) features.device_width / (double) features.device_height * 100.0 );\r
-                       if(ratio_feat <= ratio_this)\r
-                       {\r
-                               return true;\r
-                       }\r
-               }\r
-               break;\r
-\r
-       case media_feature_color:\r
-               if(check_as_bool)\r
-               {\r
-                       return (features.color != 0);\r
-               } else if(features.color == val)\r
-               {\r
-                       return true;\r
-               }\r
-               break;\r
-       case media_feature_min_color:\r
-               if(features.color >= val)\r
-               {\r
-                       return true;\r
-               }\r
-               break;\r
-       case media_feature_max_color:\r
-               if(features.color <= val)\r
-               {\r
-                       return true;\r
-               }\r
-               break;\r
-\r
-       case media_feature_color_index:\r
-               if(check_as_bool)\r
-               {\r
-                       return (features.color_index != 0);\r
-               } else if(features.color_index == val)\r
-               {\r
-                       return true;\r
-               }\r
-               break;\r
-       case media_feature_min_color_index:\r
-               if(features.color_index >= val)\r
-               {\r
-                       return true;\r
-               }\r
-               break;\r
-       case media_feature_max_color_index:\r
-               if(features.color_index <= val)\r
-               {\r
-                       return true;\r
-               }\r
-               break;\r
-\r
-       case media_feature_monochrome:\r
-               if(check_as_bool)\r
-               {\r
-                       return (features.monochrome != 0);\r
-               } else if(features.monochrome == val)\r
-               {\r
-                       return true;\r
-               }\r
-               break;\r
-       case media_feature_min_monochrome:\r
-               if(features.monochrome >= val)\r
-               {\r
-                       return true;\r
-               }\r
-               break;\r
-       case media_feature_max_monochrome:\r
-               if(features.monochrome <= val)\r
-               {\r
-                       return true;\r
-               }\r
-               break;\r
-\r
-       case media_feature_resolution:\r
-               if(features.resolution == val)\r
-               {\r
-                       return true;\r
-               }\r
-               break;\r
-       case media_feature_min_resolution:\r
-               if(features.resolution >= val)\r
-               {\r
-                       return true;\r
-               }\r
-               break;\r
-       case media_feature_max_resolution:\r
-               if(features.resolution <= val)\r
-               {\r
-                       return true;\r
-               }\r
-               break;\r
-       default:\r
-               return false;\r
-       }\r
-\r
-       return false;\r
-}\r
+#include "html.h"
+#include "media_query.h"
+#include "document.h"
+
+
+litehtml::media_query::media_query()
+{
+       m_media_type    = media_type_all;
+       m_not                   = false;
+}
+
+litehtml::media_query::media_query( const media_query& val )
+{
+       m_not                   = val.m_not;
+       m_expressions   = val.m_expressions;
+       m_media_type    = val.m_media_type;
+}
+
+litehtml::media_query::ptr litehtml::media_query::create_from_string(const tstring& str, const std::shared_ptr<document>& doc)
+{
+       media_query::ptr query = std::make_shared<media_query>();
+
+       string_vector tokens;
+       split_string(str, tokens, _t(" \t\r\n"), _t(""), _t("("));
+
+       for(string_vector::iterator tok = tokens.begin(); tok != tokens.end(); tok++)
+       {
+               if((*tok) == _t("not"))
+               {
+                       query->m_not = true;
+               } else if(tok->at(0) == _t('('))
+               {
+                       tok->erase(0, 1);
+                       if(tok->at(tok->length() - 1) == _t(')'))
+                       {
+                               tok->erase(tok->length() - 1, 1);
+                       }
+                       media_query_expression expr;
+                       string_vector expr_tokens;
+                       split_string((*tok), expr_tokens, _t(":"));
+                       if(!expr_tokens.empty())
+                       {
+                               trim(expr_tokens[0]);
+                               expr.feature = (media_feature) value_index(expr_tokens[0], media_feature_strings, media_feature_none);
+                               if(expr.feature != media_feature_none)
+                               {
+                                       if(expr_tokens.size() == 1)
+                                       {
+                                               expr.check_as_bool = true;
+                                       } else
+                                       {
+                                               trim(expr_tokens[1]);
+                                               expr.check_as_bool = false;
+                                               if(expr.feature == media_feature_orientation)
+                                               {
+                                                       expr.val = value_index(expr_tokens[1], media_orientation_strings, media_orientation_landscape);
+                                               } else
+                                               {
+                                                       tstring::size_type slash_pos = expr_tokens[1].find(_t('/'));
+                                                       if( slash_pos != tstring::npos )
+                                                       {
+                                                               tstring val1 = expr_tokens[1].substr(0, slash_pos);
+                                                               tstring val2 = expr_tokens[1].substr(slash_pos + 1);
+                                                               trim(val1);
+                                                               trim(val2);
+                                                               expr.val = t_atoi(val1.c_str());
+                                                               expr.val2 = t_atoi(val2.c_str());
+                                                       } else
+                                                       {
+                                                               css_length length;
+                                                               length.fromString(expr_tokens[1]);
+                                                               if(length.units() == css_units_dpcm)
+                                                               {
+                                                                       expr.val = (int) (length.val() * 2.54);
+                                                               } else if(length.units() == css_units_dpi)
+                                                               {
+                                                                       expr.val = (int) (length.val() * 2.54);
+                                                               } else
+                                                               {
+                                                                       if(doc)
+                                                                       {
+                                                                               doc->cvt_units(length, doc->container()->get_default_font_size());
+                                                                       }
+                                                                       expr.val = (int) length.val();
+                                                               }
+                                                       }
+                                               }
+                                       }
+                                       query->m_expressions.push_back(expr);
+                               }
+                       }
+               } else
+               {
+                       query->m_media_type = (media_type) value_index((*tok), media_type_strings, media_type_all);
+
+               }
+       }
+
+       return query;
+}
+
+bool litehtml::media_query::check( const media_features& features ) const
+{
+       bool res = false;
+       if(m_media_type == media_type_all || m_media_type == features.type)
+       {
+               res = true;
+               for(media_query_expression::vector::const_iterator expr = m_expressions.begin(); expr != m_expressions.end() && res; expr++)
+               {
+                       if(!expr->check(features))
+                       {
+                               res = false;
+                       }
+               }
+       }
+
+       if(m_not)
+       {
+               res = !res;
+       }
+
+       return res;
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+litehtml::media_query_list::ptr litehtml::media_query_list::create_from_string(const tstring& str, const std::shared_ptr<document>& doc)
+{
+       media_query_list::ptr list = std::make_shared<media_query_list>();
+
+       string_vector tokens;
+       split_string(str, tokens, _t(","));
+
+       for(string_vector::iterator tok = tokens.begin(); tok != tokens.end(); tok++)
+       {
+               trim(*tok);
+               lcase(*tok);
+
+               litehtml::media_query::ptr query = media_query::create_from_string(*tok, doc);
+               if(query)
+               {
+                       list->m_queries.push_back(query);
+               }
+       }
+       if(list->m_queries.empty())
+       {
+               list = 0;
+       }
+
+       return list;
+}
+
+bool litehtml::media_query_list::apply_media_features( const media_features& features )
+{
+       bool apply = false;
+       
+       for(media_query::vector::iterator iter = m_queries.begin(); iter != m_queries.end() && !apply; iter++)
+       {
+               if((*iter)->check(features))
+               {
+                       apply = true;
+               }
+       }
+
+       bool ret = (apply != m_is_used);
+       m_is_used = apply;
+       return ret;
+}
+
+bool litehtml::media_query_expression::check( const media_features& features ) const
+{
+       switch(feature)
+       {
+       case media_feature_width:
+               if(check_as_bool)
+               {
+                       return (features.width != 0);
+               } else if(features.width == val)
+               {
+                       return true;
+               }
+               break;
+       case media_feature_min_width:
+               if(features.width >= val)
+               {
+                       return true;
+               }
+               break;
+       case media_feature_max_width:
+               if(features.width <= val)
+               {
+                       return true;
+               }
+               break;
+       case media_feature_height:
+               if(check_as_bool)
+               {
+                       return (features.height != 0);
+               } else if(features.height == val)
+               {
+                       return true;
+               }
+               break;
+       case media_feature_min_height:
+               if(features.height >= val)
+               {
+                       return true;
+               }
+               break;
+       case media_feature_max_height:
+               if(features.height <= val)
+               {
+                       return true;
+               }
+               break;
+
+       case media_feature_device_width:
+               if(check_as_bool)
+               {
+                       return (features.device_width != 0);
+               } else if(features.device_width == val)
+               {
+                       return true;
+               }
+               break;
+       case media_feature_min_device_width:
+               if(features.device_width >= val)
+               {
+                       return true;
+               }
+               break;
+       case media_feature_max_device_width:
+               if(features.device_width <= val)
+               {
+                       return true;
+               }
+               break;
+       case media_feature_device_height:
+               if(check_as_bool)
+               {
+                       return (features.device_height != 0);
+               } else if(features.device_height == val)
+               {
+                       return true;
+               }
+               break;
+       case media_feature_min_device_height:
+               if(features.device_height <= val)
+               {
+                       return true;
+               }
+               break;
+       case media_feature_max_device_height:
+               if(features.device_height <= val)
+               {
+                       return true;
+               }
+               break;
+
+       case media_feature_orientation:
+               if(features.height >= features.width)
+               {
+                       if(val == media_orientation_portrait)
+                       {
+                               return true;
+                       }
+               } else
+               {
+                       if(val == media_orientation_landscape)
+                       {
+                               return true;
+                       }
+               }
+               break;
+       case media_feature_aspect_ratio:
+               if(features.height && val2)
+               {
+                       int ratio_this = round_d( (double) val / (double) val2 * 100 );
+                       int ratio_feat = round_d( (double) features.width / (double) features.height * 100.0 );
+                       if(ratio_this == ratio_feat)
+                       {
+                               return true;
+                       }
+               }
+               break;
+       case media_feature_min_aspect_ratio:
+               if(features.height && val2)
+               {
+                       int ratio_this = round_d( (double) val / (double) val2 * 100 );
+                       int ratio_feat = round_d( (double) features.width / (double) features.height * 100.0 );
+                       if(ratio_feat >= ratio_this)
+                       {
+                               return true;
+                       }
+               }
+               break;
+       case media_feature_max_aspect_ratio:
+               if(features.height && val2)
+               {
+                       int ratio_this = round_d( (double) val / (double) val2 * 100 );
+                       int ratio_feat = round_d( (double) features.width / (double) features.height * 100.0 );
+                       if(ratio_feat <= ratio_this)
+                       {
+                               return true;
+                       }
+               }
+               break;
+
+       case media_feature_device_aspect_ratio:
+               if(features.device_height && val2)
+               {
+                       int ratio_this = round_d( (double) val / (double) val2 * 100 );
+                       int ratio_feat = round_d( (double) features.device_width / (double) features.device_height * 100.0 );
+                       if(ratio_feat == ratio_this)
+                       {
+                               return true;
+                       }
+               }
+               break;
+       case media_feature_min_device_aspect_ratio:
+               if(features.device_height && val2)
+               {
+                       int ratio_this = round_d( (double) val / (double) val2 * 100 );
+                       int ratio_feat = round_d( (double) features.device_width / (double) features.device_height * 100.0 );
+                       if(ratio_feat >= ratio_this)
+                       {
+                               return true;
+                       }
+               }
+               break;
+       case media_feature_max_device_aspect_ratio:
+               if(features.device_height && val2)
+               {
+                       int ratio_this = round_d( (double) val / (double) val2 * 100 );
+                       int ratio_feat = round_d( (double) features.device_width / (double) features.device_height * 100.0 );
+                       if(ratio_feat <= ratio_this)
+                       {
+                               return true;
+                       }
+               }
+               break;
+
+       case media_feature_color:
+               if(check_as_bool)
+               {
+                       return (features.color != 0);
+               } else if(features.color == val)
+               {
+                       return true;
+               }
+               break;
+       case media_feature_min_color:
+               if(features.color >= val)
+               {
+                       return true;
+               }
+               break;
+       case media_feature_max_color:
+               if(features.color <= val)
+               {
+                       return true;
+               }
+               break;
+
+       case media_feature_color_index:
+               if(check_as_bool)
+               {
+                       return (features.color_index != 0);
+               } else if(features.color_index == val)
+               {
+                       return true;
+               }
+               break;
+       case media_feature_min_color_index:
+               if(features.color_index >= val)
+               {
+                       return true;
+               }
+               break;
+       case media_feature_max_color_index:
+               if(features.color_index <= val)
+               {
+                       return true;
+               }
+               break;
+
+       case media_feature_monochrome:
+               if(check_as_bool)
+               {
+                       return (features.monochrome != 0);
+               } else if(features.monochrome == val)
+               {
+                       return true;
+               }
+               break;
+       case media_feature_min_monochrome:
+               if(features.monochrome >= val)
+               {
+                       return true;
+               }
+               break;
+       case media_feature_max_monochrome:
+               if(features.monochrome <= val)
+               {
+                       return true;
+               }
+               break;
+
+       case media_feature_resolution:
+               if(features.resolution == val)
+               {
+                       return true;
+               }
+               break;
+       case media_feature_min_resolution:
+               if(features.resolution >= val)
+               {
+                       return true;
+               }
+               break;
+       case media_feature_max_resolution:
+               if(features.resolution <= val)
+               {
+                       return true;
+               }
+               break;
+       default:
+               return false;
+       }
+
+       return false;
+}