blob: 0ac9d52d06646d2f9e9a27f75c77d47bce6a402f [file] [log] [blame]
/*
* Copyright (C) 2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "third_party/blink/renderer/platform/fonts/font_selection_algorithm.h"
namespace blink {
auto FontSelectionAlgorithm::StretchDistance(
FontSelectionCapabilities capabilities) const -> DistanceResult {
auto width = capabilities.width;
DCHECK(width.IsValid());
if (width.Includes(request_.width))
return {FontSelectionValue(), request_.width};
if (request_.width > NormalWidthValue()) {
if (width.minimum > request_.width)
return {width.minimum - request_.width, width.minimum};
DCHECK(width.maximum < request_.width);
auto threshold =
std::max(request_.width, capabilities_bounds_.width.maximum);
return {threshold - width.maximum, width.maximum};
}
if (width.maximum < request_.width)
return {request_.width - width.maximum, width.maximum};
DCHECK(width.minimum > request_.width);
auto threshold = std::min(request_.width, capabilities_bounds_.width.minimum);
return {width.minimum - threshold, width.minimum};
}
auto FontSelectionAlgorithm::StyleDistance(
FontSelectionCapabilities capabilities) const -> DistanceResult {
auto slope = capabilities.slope;
DCHECK(slope.IsValid());
if (slope.Includes(request_.slope))
return {FontSelectionValue(), request_.slope};
if (request_.slope >= ItalicThreshold()) {
if (slope.minimum > request_.slope)
return {slope.minimum - request_.slope, slope.minimum};
DCHECK(request_.slope > slope.maximum);
auto threshold =
std::max(request_.slope, capabilities_bounds_.slope.maximum);
return {threshold - slope.maximum, slope.maximum};
}
if (request_.slope >= FontSelectionValue()) {
if (slope.maximum >= FontSelectionValue() && slope.maximum < request_.slope)
return {request_.slope - slope.maximum, slope.maximum};
if (slope.minimum > request_.slope)
return {slope.minimum, slope.minimum};
DCHECK(slope.maximum < FontSelectionValue());
auto threshold =
std::max(request_.slope, capabilities_bounds_.slope.maximum);
return {threshold - slope.maximum, slope.maximum};
}
if (request_.slope > -ItalicThreshold()) {
if (slope.minimum > request_.slope && slope.minimum <= FontSelectionValue())
return {slope.minimum - request_.slope, slope.minimum};
if (slope.maximum < request_.slope)
return {-slope.maximum, slope.maximum};
DCHECK(slope.minimum > FontSelectionValue());
auto threshold =
std::min(request_.slope, capabilities_bounds_.slope.minimum);
return {slope.minimum - threshold, slope.minimum};
}
if (slope.maximum < request_.slope)
return {request_.slope - slope.maximum, slope.maximum};
DCHECK(slope.minimum > request_.slope);
auto threshold = std::min(request_.slope, capabilities_bounds_.slope.minimum);
return {slope.minimum - threshold, slope.minimum};
}
auto FontSelectionAlgorithm::WeightDistance(
FontSelectionCapabilities capabilities) const -> DistanceResult {
auto weight = capabilities.weight;
DCHECK(weight.IsValid());
if (weight.Includes(request_.weight))
return {FontSelectionValue(), request_.weight};
if (request_.weight >= LowerWeightSearchThreshold() &&
request_.weight <= UpperWeightSearchThreshold()) {
if (weight.minimum > request_.weight &&
weight.minimum <= UpperWeightSearchThreshold())
return {weight.minimum - request_.weight, weight.minimum};
if (weight.maximum < request_.weight)
return {UpperWeightSearchThreshold() - weight.maximum, weight.maximum};
DCHECK(weight.minimum > UpperWeightSearchThreshold());
auto threshold =
std::min(request_.weight, capabilities_bounds_.weight.minimum);
return {weight.minimum - threshold, weight.minimum};
}
if (request_.weight < LowerWeightSearchThreshold()) {
if (weight.maximum < request_.weight)
return {request_.weight - weight.maximum, weight.maximum};
DCHECK(weight.minimum > request_.weight);
auto threshold =
std::min(request_.weight, capabilities_bounds_.weight.minimum);
return {weight.minimum - threshold, weight.minimum};
}
DCHECK(request_.weight >= UpperWeightSearchThreshold());
if (weight.minimum > request_.weight)
return {weight.minimum - request_.weight, weight.minimum};
DCHECK(weight.maximum < request_.weight);
auto threshold =
std::max(request_.weight, capabilities_bounds_.weight.maximum);
return {threshold - weight.maximum, weight.maximum};
}
bool FontSelectionAlgorithm::IsBetterMatchForRequest(
const FontSelectionCapabilities& firstCapabilities,
const FontSelectionCapabilities& secondCapabilities) {
auto stretchDistanceFirst = StretchDistance(firstCapabilities).distance;
auto stretchDistanceSecond = StretchDistance(secondCapabilities).distance;
if (stretchDistanceFirst < stretchDistanceSecond)
return true;
if (stretchDistanceFirst > stretchDistanceSecond)
return false;
auto styleDistanceFirst = StyleDistance(firstCapabilities).distance;
auto styleDistanceSecond = StyleDistance(secondCapabilities).distance;
if (styleDistanceFirst < styleDistanceSecond)
return true;
if (styleDistanceFirst > styleDistanceSecond)
return false;
auto weightDistanceFirst = WeightDistance(firstCapabilities).distance;
auto weightDistanceSecond = WeightDistance(secondCapabilities).distance;
if (weightDistanceFirst < weightDistanceSecond)
return true;
return false;
}
} // namespace blink