[core] Introduce a fully-evaluated tuple type for layout properties
This commit is contained in:
@@ -9,7 +9,7 @@ SymbolInstance::SymbolInstance(Anchor& anchor,
|
||||
const GeometryCoordinates& line,
|
||||
const std::pair<Shaping, Shaping>& shapedTextOrientations,
|
||||
const PositionedIcon& shapedIcon,
|
||||
const SymbolLayoutProperties::Evaluated& layout,
|
||||
const SymbolLayoutProperties::PossiblyEvaluated& layout,
|
||||
const bool addToBuffers,
|
||||
const uint32_t index_,
|
||||
const float textBoxScale,
|
||||
|
||||
@@ -16,7 +16,7 @@ public:
|
||||
const GeometryCoordinates& line,
|
||||
const std::pair<Shaping, Shaping>& shapedTextOrientations,
|
||||
const PositionedIcon& shapedIcon,
|
||||
const style::SymbolLayoutProperties::Evaluated&,
|
||||
const style::SymbolLayoutProperties::PossiblyEvaluated&,
|
||||
const bool inside,
|
||||
const uint32_t index,
|
||||
const float textBoxScale,
|
||||
|
||||
@@ -78,7 +78,7 @@ private:
|
||||
const float zoom;
|
||||
const MapMode mode;
|
||||
|
||||
style::SymbolLayoutProperties::Evaluated layout;
|
||||
style::SymbolLayoutProperties::PossiblyEvaluated layout;
|
||||
float textMaxSize;
|
||||
|
||||
SpriteAtlas& spriteAtlas;
|
||||
|
||||
@@ -29,7 +29,7 @@ public:
|
||||
void upload(gl::Context&) override;
|
||||
void render(Painter&, PaintParameters&, const style::Layer&, const RenderTile&) override;
|
||||
|
||||
style::LineLayoutProperties::Evaluated layout;
|
||||
style::LineLayoutProperties::PossiblyEvaluated layout;
|
||||
|
||||
gl::VertexVector<LineLayoutVertex> vertices;
|
||||
gl::IndexVector<gl::Triangles> triangles;
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace mbgl {
|
||||
|
||||
using namespace style;
|
||||
|
||||
SymbolBucket::SymbolBucket(style::SymbolLayoutProperties::Evaluated layout_,
|
||||
SymbolBucket::SymbolBucket(style::SymbolLayoutProperties::PossiblyEvaluated layout_,
|
||||
const std::map<std::string, std::pair<
|
||||
style::IconPaintProperties::Evaluated, style::TextPaintProperties::Evaluated>>& layerPaintProperties,
|
||||
float zoom,
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace mbgl {
|
||||
|
||||
class SymbolBucket : public Bucket {
|
||||
public:
|
||||
SymbolBucket(style::SymbolLayoutProperties::Evaluated,
|
||||
SymbolBucket(style::SymbolLayoutProperties::PossiblyEvaluated,
|
||||
const std::map<std::string, std::pair<style::IconPaintProperties::Evaluated, style::TextPaintProperties::Evaluated>>&,
|
||||
float zoom,
|
||||
bool sdfIcons,
|
||||
@@ -29,7 +29,7 @@ public:
|
||||
bool hasIconData() const;
|
||||
bool hasCollisionBoxData() const;
|
||||
|
||||
const style::SymbolLayoutProperties::Evaluated layout;
|
||||
const style::SymbolLayoutProperties::PossiblyEvaluated layout;
|
||||
const bool sdfIcons;
|
||||
const bool iconsNeedLinear;
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ TextPaintProperties::Evaluated SymbolLayer::Impl::textPaintProperties() const {
|
||||
}
|
||||
|
||||
|
||||
SymbolPropertyValues SymbolLayer::Impl::iconPropertyValues(const SymbolLayoutProperties::Evaluated& layout_) const {
|
||||
SymbolPropertyValues SymbolLayer::Impl::iconPropertyValues(const SymbolLayoutProperties::PossiblyEvaluated& layout_) const {
|
||||
return SymbolPropertyValues {
|
||||
layout_.get<IconRotationAlignment>(), // icon-pitch-alignment is not yet implemented; inherit the rotation alignment
|
||||
layout_.get<IconRotationAlignment>(),
|
||||
@@ -83,7 +83,7 @@ SymbolPropertyValues SymbolLayer::Impl::iconPropertyValues(const SymbolLayoutPro
|
||||
};
|
||||
}
|
||||
|
||||
SymbolPropertyValues SymbolLayer::Impl::textPropertyValues(const SymbolLayoutProperties::Evaluated& layout_) const {
|
||||
SymbolPropertyValues SymbolLayer::Impl::textPropertyValues(const SymbolLayoutProperties::PossiblyEvaluated& layout_) const {
|
||||
return SymbolPropertyValues {
|
||||
layout_.get<TextPitchAlignment>(),
|
||||
layout_.get<TextRotationAlignment>(),
|
||||
|
||||
@@ -72,8 +72,8 @@ public:
|
||||
IconPaintProperties::Evaluated iconPaintProperties() const;
|
||||
TextPaintProperties::Evaluated textPaintProperties() const;
|
||||
|
||||
SymbolPropertyValues iconPropertyValues(const SymbolLayoutProperties::Evaluated&) const;
|
||||
SymbolPropertyValues textPropertyValues(const SymbolLayoutProperties::Evaluated&) const;
|
||||
SymbolPropertyValues iconPropertyValues(const SymbolLayoutProperties::PossiblyEvaluated&) const;
|
||||
SymbolPropertyValues textPropertyValues(const SymbolLayoutProperties::PossiblyEvaluated&) const;
|
||||
|
||||
SymbolLayoutProperties layout;
|
||||
SymbolPaintProperties paint;
|
||||
|
||||
@@ -16,7 +16,7 @@ class LayoutProperty {
|
||||
public:
|
||||
using UnevaluatedType = PropertyValue<T>;
|
||||
using EvaluatorType = PropertyEvaluator<T>;
|
||||
using EvaluatedType = T;
|
||||
using PossiblyEvaluatedType = T;
|
||||
using Type = T;
|
||||
};
|
||||
|
||||
@@ -25,7 +25,7 @@ class DataDrivenLayoutProperty {
|
||||
public:
|
||||
using UnevaluatedType = DataDrivenPropertyValue<T>;
|
||||
using EvaluatorType = DataDrivenPropertyEvaluator<T>;
|
||||
using EvaluatedType = PossiblyEvaluatedPropertyValue<T>;
|
||||
using PossiblyEvaluatedType = PossiblyEvaluatedPropertyValue<T>;
|
||||
using Type = T;
|
||||
};
|
||||
|
||||
@@ -33,23 +33,65 @@ template <class... Ps>
|
||||
class LayoutProperties {
|
||||
public:
|
||||
using Properties = TypeList<Ps...>;
|
||||
using EvaluatedTypes = TypeList<typename Ps::EvaluatedType...>;
|
||||
using UnevaluatedTypes = TypeList<typename Ps::UnevaluatedType...>;
|
||||
|
||||
template <class TypeList>
|
||||
using Tuple = IndexedTuple<Properties, TypeList>;
|
||||
|
||||
/*
|
||||
For layout properties we implement a two step evaluation process: if you have a zoom level,
|
||||
you can evaluate a set of unevaluated property values, producing a set of possibly evaluated
|
||||
values, where non-data-driven property values have been fully evaluated, and data-driven values
|
||||
have not.
|
||||
|
||||
Once you also have a particular feature, you can evaluate that set of possibly evaluated values
|
||||
fully, producing a set of fully evaluated values.
|
||||
|
||||
This is in theory maximally efficient in terms of avoiding repeated evaluation of camera
|
||||
functions, though it's more of a historical accident that a purposeful optimization.
|
||||
*/
|
||||
|
||||
using UnevaluatedTypes = TypeList<typename Ps::UnevaluatedType...>;
|
||||
using PossiblyEvaluatedTypes = TypeList<typename Ps::PossiblyEvaluatedType...>;
|
||||
using EvaluatedTypes = TypeList<typename Ps::Type...>;
|
||||
|
||||
class Evaluated : public Tuple<EvaluatedTypes> {
|
||||
public:
|
||||
using Tuple<EvaluatedTypes>::Tuple;
|
||||
};
|
||||
|
||||
class PossiblyEvaluated : public Tuple<PossiblyEvaluatedTypes> {
|
||||
public:
|
||||
using Tuple<PossiblyEvaluatedTypes>::Tuple;
|
||||
|
||||
template <class T>
|
||||
static T evaluate(float, const GeometryTileFeature&, const T& t, const T&) {
|
||||
return t;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static T evaluate(float z, const GeometryTileFeature& feature,
|
||||
const PossiblyEvaluatedPropertyValue<T>& v, const T& defaultValue) {
|
||||
return v.match(
|
||||
[&] (const T& t) {
|
||||
return t;
|
||||
},
|
||||
[&] (const SourceFunction<T>& t) {
|
||||
return t.evaluate(feature, defaultValue);
|
||||
},
|
||||
[&] (const CompositeFunction<T>& t) {
|
||||
return t.evaluate(z, feature, defaultValue);
|
||||
});
|
||||
}
|
||||
|
||||
template <class P>
|
||||
typename P::Type evaluate(float z, const GeometryTileFeature& feature) const {
|
||||
using T = typename P::Type;
|
||||
return this->template get<P>().match(
|
||||
[&] (const T& t) { return t; },
|
||||
[&] (const SourceFunction<T>& t) { return t.evaluate(feature, P::defaultValue()); },
|
||||
[&] (const CompositeFunction<T>& t) { return t.evaluate(z, feature, P::defaultValue()); });
|
||||
auto evaluate(float z, const GeometryTileFeature& feature) const {
|
||||
return evaluate(z, feature, this->template get<P>(), P::defaultValue());
|
||||
}
|
||||
|
||||
Evaluated evaluate(float z, const GeometryTileFeature& feature) const {
|
||||
return Evaluated {
|
||||
evaluate<Ps>(z, feature)...
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -65,8 +107,8 @@ public:
|
||||
.evaluate(Evaluator(parameters, P::defaultValue()));
|
||||
}
|
||||
|
||||
Evaluated evaluate(const PropertyEvaluationParameters& parameters) const {
|
||||
return Evaluated {
|
||||
PossiblyEvaluated evaluate(const PropertyEvaluationParameters& parameters) const {
|
||||
return PossiblyEvaluated {
|
||||
evaluate<Ps>(parameters)...
|
||||
};
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ const float globalMinScale = 0.5f; // underscale by 1 zoom level
|
||||
SymbolQuad getIconQuad(const Anchor& anchor,
|
||||
const PositionedIcon& shapedIcon,
|
||||
const GeometryCoordinates& line,
|
||||
const SymbolLayoutProperties::Evaluated& layout,
|
||||
const SymbolLayoutProperties::PossiblyEvaluated& layout,
|
||||
const style::SymbolPlacementType placement,
|
||||
const Shaping& shapedText) {
|
||||
auto image = *(shapedIcon.image);
|
||||
@@ -292,7 +292,7 @@ SymbolQuads getGlyphQuads(Anchor& anchor,
|
||||
const Shaping& shapedText,
|
||||
const float boxScale,
|
||||
const GeometryCoordinates& line,
|
||||
const SymbolLayoutProperties::Evaluated& layout,
|
||||
const SymbolLayoutProperties::PossiblyEvaluated& layout,
|
||||
const style::SymbolPlacementType placement,
|
||||
const GlyphPositions& face) {
|
||||
const float textRotate = layout.get<TextRotate>() * util::DEG2RAD;
|
||||
|
||||
@@ -54,7 +54,7 @@ typedef std::vector<SymbolQuad> SymbolQuads;
|
||||
SymbolQuad getIconQuad(const Anchor& anchor,
|
||||
const PositionedIcon& shapedIcon,
|
||||
const GeometryCoordinates& line,
|
||||
const style::SymbolLayoutProperties::Evaluated&,
|
||||
const style::SymbolLayoutProperties::PossiblyEvaluated&,
|
||||
style::SymbolPlacementType placement,
|
||||
const Shaping& shapedText);
|
||||
|
||||
@@ -62,7 +62,7 @@ SymbolQuads getGlyphQuads(Anchor& anchor,
|
||||
const Shaping& shapedText,
|
||||
const float boxScale,
|
||||
const GeometryCoordinates& line,
|
||||
const style::SymbolLayoutProperties::Evaluated&,
|
||||
const style::SymbolLayoutProperties::PossiblyEvaluated&,
|
||||
style::SymbolPlacementType placement,
|
||||
const GlyphPositions& face);
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ TEST(Buckets, LineBucket) {
|
||||
}
|
||||
|
||||
TEST(Buckets, SymbolBucket) {
|
||||
style::SymbolLayoutProperties::Evaluated layout;
|
||||
style::SymbolLayoutProperties::PossiblyEvaluated layout;
|
||||
bool sdfIcons = false;
|
||||
bool iconsNeedLinear = false;
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ using namespace mbgl;
|
||||
using namespace mbgl::style;
|
||||
|
||||
TEST(getIconQuads, normal) {
|
||||
SymbolLayoutProperties::Evaluated layout;
|
||||
SymbolLayoutProperties::PossiblyEvaluated layout;
|
||||
Anchor anchor(2.0, 3.0, 0.0, 0.5f, 0);
|
||||
SpriteAtlasElement image = {
|
||||
Rect<uint16_t>( 0, 0, 15, 11 ),
|
||||
@@ -59,7 +59,7 @@ TEST(getIconQuads, style) {
|
||||
|
||||
// none
|
||||
{
|
||||
SymbolLayoutProperties::Evaluated layout;
|
||||
SymbolLayoutProperties::PossiblyEvaluated layout;
|
||||
SymbolQuad quad =
|
||||
getIconQuad(anchor, shapedIcon, line, layout, SymbolPlacementType::Point, shapedText);
|
||||
|
||||
@@ -80,7 +80,7 @@ TEST(getIconQuads, style) {
|
||||
|
||||
// width
|
||||
{
|
||||
SymbolLayoutProperties::Evaluated layout;
|
||||
SymbolLayoutProperties::PossiblyEvaluated layout;
|
||||
layout.get<TextSize>() = 24.0f;
|
||||
layout.get<IconTextFit>() = IconTextFitType::Width;
|
||||
SymbolQuad quad =
|
||||
@@ -98,7 +98,7 @@ TEST(getIconQuads, style) {
|
||||
|
||||
// width x textSize
|
||||
{
|
||||
SymbolLayoutProperties::Evaluated layout;
|
||||
SymbolLayoutProperties::PossiblyEvaluated layout;
|
||||
layout.get<TextSize>() = 12.0f;
|
||||
layout.get<IconTextFit>() = IconTextFitType::Width;
|
||||
SymbolQuad quad =
|
||||
@@ -116,7 +116,7 @@ TEST(getIconQuads, style) {
|
||||
|
||||
// width x textSize + padding
|
||||
{
|
||||
SymbolLayoutProperties::Evaluated layout;
|
||||
SymbolLayoutProperties::PossiblyEvaluated layout;
|
||||
layout.get<TextSize>() = 12.0f;
|
||||
layout.get<IconTextFit>() = IconTextFitType::Width;
|
||||
layout.get<IconTextFitPadding>()[0] = 5.0f;
|
||||
@@ -138,7 +138,7 @@ TEST(getIconQuads, style) {
|
||||
|
||||
// height
|
||||
{
|
||||
SymbolLayoutProperties::Evaluated layout;
|
||||
SymbolLayoutProperties::PossiblyEvaluated layout;
|
||||
layout.get<TextSize>() = 24.0f;
|
||||
layout.get<IconTextFit>() = IconTextFitType::Height;
|
||||
SymbolQuad quad =
|
||||
@@ -156,7 +156,7 @@ TEST(getIconQuads, style) {
|
||||
|
||||
// height x textSize
|
||||
{
|
||||
SymbolLayoutProperties::Evaluated layout;
|
||||
SymbolLayoutProperties::PossiblyEvaluated layout;
|
||||
layout.get<TextSize>() = 12.0f;
|
||||
layout.get<IconTextFit>() = IconTextFitType::Height;
|
||||
SymbolQuad quad =
|
||||
@@ -174,7 +174,7 @@ TEST(getIconQuads, style) {
|
||||
|
||||
// height x textSize + padding
|
||||
{
|
||||
SymbolLayoutProperties::Evaluated layout;
|
||||
SymbolLayoutProperties::PossiblyEvaluated layout;
|
||||
layout.get<TextSize>() = 12.0f;
|
||||
layout.get<IconTextFit>() = IconTextFitType::Height;
|
||||
layout.get<IconTextFitPadding>()[0] = 5.0f;
|
||||
@@ -196,7 +196,7 @@ TEST(getIconQuads, style) {
|
||||
|
||||
// both
|
||||
{
|
||||
SymbolLayoutProperties::Evaluated layout;
|
||||
SymbolLayoutProperties::PossiblyEvaluated layout;
|
||||
layout.get<TextSize>() = 24.0f;
|
||||
layout.get<IconTextFit>() = IconTextFitType::Both;
|
||||
SymbolQuad quad =
|
||||
@@ -214,7 +214,7 @@ TEST(getIconQuads, style) {
|
||||
|
||||
// both x textSize
|
||||
{
|
||||
SymbolLayoutProperties::Evaluated layout;
|
||||
SymbolLayoutProperties::PossiblyEvaluated layout;
|
||||
layout.get<TextSize>() = 12.0f;
|
||||
layout.get<IconTextFit>() = IconTextFitType::Both;
|
||||
SymbolQuad quad =
|
||||
@@ -232,7 +232,7 @@ TEST(getIconQuads, style) {
|
||||
|
||||
// both x textSize + padding
|
||||
{
|
||||
SymbolLayoutProperties::Evaluated layout;
|
||||
SymbolLayoutProperties::PossiblyEvaluated layout;
|
||||
layout.get<TextSize>() = 12.0f;
|
||||
layout.get<IconTextFit>() = IconTextFitType::Both;
|
||||
layout.get<IconTextFitPadding>()[0] = 5.0f;
|
||||
@@ -254,7 +254,7 @@ TEST(getIconQuads, style) {
|
||||
|
||||
// both x textSize + padding t/r/b/l
|
||||
{
|
||||
SymbolLayoutProperties::Evaluated layout;
|
||||
SymbolLayoutProperties::PossiblyEvaluated layout;
|
||||
layout.get<TextSize>() = 12.0f;
|
||||
layout.get<IconTextFit>() = IconTextFitType::Both;
|
||||
layout.get<IconTextFitPadding>()[0] = 0.0f;
|
||||
|
||||
@@ -60,7 +60,7 @@ TEST(VectorTile, Issue7615) {
|
||||
|
||||
style::SymbolLayer symbolLayer("symbol", "source");
|
||||
auto symbolBucket = std::make_shared<SymbolBucket>(
|
||||
style::SymbolLayoutProperties::Evaluated(),
|
||||
style::SymbolLayoutProperties::PossiblyEvaluated(),
|
||||
std::map<
|
||||
std::string,
|
||||
std::pair<style::IconPaintProperties::Evaluated, style::TextPaintProperties::Evaluated>>(),
|
||||
@@ -94,4 +94,4 @@ TEST(VectorTile, Issue8542) {
|
||||
// Query before data is set
|
||||
std::vector<Feature> result;
|
||||
tile.querySourceFeatures(result, { { {"layer"} }, {} });
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user