void reportMediaQueryWarningIfNeeded(Document* document, const MediaQuerySet* mediaQuerySet) { if (!mediaQuerySet || !document) return; auto& mediaQueries = mediaQuerySet->queryVector(); const size_t queryCount = mediaQueries.size(); if (!queryCount) return; for (size_t i = 0; i < queryCount; ++i) { const MediaQuery* query = mediaQueries[i].get(); String mediaType = query->mediaType(); if (!query->ignored() && !equalIgnoringCase(mediaType, "print")) { auto& expressions = query->expressions(); for (size_t j = 0; j < expressions.size(); ++j) { const MediaQueryExp* exp = expressions.at(j).get(); if (exp->mediaFeature() == MediaFeatureNames::resolutionMediaFeature || exp->mediaFeature() == MediaFeatureNames::max_resolutionMediaFeature || exp->mediaFeature() == MediaFeatureNames::min_resolutionMediaFeature) { CSSValue* cssValue = exp->value(); if (cssValue && cssValue->isPrimitiveValue()) { CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(cssValue); if (primitiveValue->isDotsPerInch() || primitiveValue->isDotsPerCentimeter()) addResolutionWarningMessageToConsole(document, mediaQuerySet->mediaText(), primitiveValue); } } } } } }
static bool evalResolution(CSSValue* value, Frame* frame, MediaFeaturePrefix op) { // According to MQ4, only 'screen', 'print' and 'speech' may match. // FIXME: What should speech match? https://www.w3.org/Style/CSS/Tracker/issues/348 float actualResolution = 0; // This checks the actual media type applied to the document, and we know // this method only got called if this media type matches the one defined // in the query. Thus, if if the document's media type is "print", the // media type of the query will either be "print" or "all". String mediaType = frame->view()->mediaType(); if (equalIgnoringCase(mediaType, "screen")) actualResolution = clampTo<float>(frame->devicePixelRatio()); else if (equalIgnoringCase(mediaType, "print")) { // The resolution of images while printing should not depend on the DPI // of the screen. Until we support proper ways of querying this info // we use 300px which is considered minimum for current printers. actualResolution = 300 / cssPixelsPerInch; } if (!value) return !!actualResolution; if (!value->isPrimitiveValue()) return false; CSSPrimitiveValue* resolution = toCSSPrimitiveValue(value); if (resolution->isNumber()) return compareValue(actualResolution, resolution->getFloatValue(), op); if (!resolution->isResolution()) return false; if (resolution->isDotsPerCentimeter()) { // To match DPCM to DPPX values, we limit to 2 decimal points. // The http://dev.w3.org/csswg/css3-values/#absolute-lengths recommends // "that the pixel unit refer to the whole number of device pixels that best // approximates the reference pixel". With that in mind, allowing 2 decimal // point precision seems appropriate. return compareValue( floorf(0.5 + 100 * actualResolution) / 100, floorf(0.5 + 100 * resolution->getFloatValue(CSSPrimitiveValue::CSS_DPPX)) / 100, op); } return compareValue(actualResolution, resolution->getFloatValue(CSSPrimitiveValue::CSS_DPPX), op); }
static void addResolutionWarningMessageToConsole(Document& document, const String& serializedExpression, const CSSPrimitiveValue& value) { static NeverDestroyed<String> mediaQueryMessage(ASCIILiteral("Consider using 'dppx' units instead of '%replacementUnits%', as in CSS '%replacementUnits%' means dots-per-CSS-%lengthUnit%, not dots-per-physical-%lengthUnit%, so does not correspond to the actual '%replacementUnits%' of a screen. In media query expression: ")); static NeverDestroyed<String> mediaValueDPI(ASCIILiteral("dpi")); static NeverDestroyed<String> mediaValueDPCM(ASCIILiteral("dpcm")); static NeverDestroyed<String> lengthUnitInch(ASCIILiteral("inch")); static NeverDestroyed<String> lengthUnitCentimeter(ASCIILiteral("centimeter")); String message; if (value.isDotsPerInch()) message = mediaQueryMessage.get().replace("%replacementUnits%", mediaValueDPI).replace("%lengthUnit%", lengthUnitInch); else if (value.isDotsPerCentimeter()) message = mediaQueryMessage.get().replace("%replacementUnits%", mediaValueDPCM).replace("%lengthUnit%", lengthUnitCentimeter); else ASSERT_NOT_REACHED(); message.append(serializedExpression); document.addConsoleMessage(MessageSource::CSS, MessageLevel::Debug, message); }