223 lines
9.8 KiB
C++
223 lines
9.8 KiB
C++
#include <mbgl/layout/symbol_instance.hpp>
|
|
#include <mbgl/style/layers/symbol_layer_properties.hpp>
|
|
#include <utility>
|
|
|
|
namespace mbgl {
|
|
|
|
using namespace style;
|
|
|
|
namespace {
|
|
|
|
const Shaping& getAnyShaping(const ShapedTextOrientations& shapedTextOrientations) {
|
|
if (shapedTextOrientations.right) return shapedTextOrientations.right;
|
|
if (shapedTextOrientations.center) return shapedTextOrientations.center;
|
|
if (shapedTextOrientations.left) return shapedTextOrientations.left;
|
|
if (shapedTextOrientations.vertical) return shapedTextOrientations.vertical;
|
|
return shapedTextOrientations.horizontal;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
SymbolInstanceSharedData::SymbolInstanceSharedData(GeometryCoordinates line_,
|
|
const ShapedTextOrientations& shapedTextOrientations,
|
|
const std::optional<PositionedIcon>& shapedIcon,
|
|
const std::optional<PositionedIcon>& verticallyShapedIcon,
|
|
const style::SymbolLayoutProperties::Evaluated& layout,
|
|
const style::SymbolPlacementType textPlacement,
|
|
const std::array<float, 2>& textOffset,
|
|
const ImageMap& imageMap,
|
|
float iconRotation,
|
|
SymbolContent iconType,
|
|
bool hasIconTextFit,
|
|
bool allowVerticalPlacement)
|
|
: line(std::move(line_)) {
|
|
// Create the quads used for rendering the icon and glyphs.
|
|
if (shapedIcon) {
|
|
iconQuads = getIconQuads(*shapedIcon, iconRotation, iconType, hasIconTextFit);
|
|
if (verticallyShapedIcon) {
|
|
verticalIconQuads = getIconQuads(*verticallyShapedIcon, iconRotation, iconType, hasIconTextFit);
|
|
}
|
|
}
|
|
|
|
bool singleLineInitialized = false;
|
|
const auto initHorizontalGlyphQuads = [&](SymbolQuads& quads, const Shaping& shaping) {
|
|
if (!shapedTextOrientations.singleLine) {
|
|
quads = getGlyphQuads(shaping, textOffset, layout, textPlacement, imageMap, allowVerticalPlacement);
|
|
return;
|
|
}
|
|
if (!singleLineInitialized) {
|
|
rightJustifiedGlyphQuads = getGlyphQuads(
|
|
shaping, textOffset, layout, textPlacement, imageMap, allowVerticalPlacement);
|
|
singleLineInitialized = true;
|
|
}
|
|
};
|
|
|
|
if (shapedTextOrientations.right) {
|
|
initHorizontalGlyphQuads(rightJustifiedGlyphQuads, shapedTextOrientations.right);
|
|
}
|
|
|
|
if (shapedTextOrientations.center) {
|
|
initHorizontalGlyphQuads(centerJustifiedGlyphQuads, shapedTextOrientations.center);
|
|
}
|
|
|
|
if (shapedTextOrientations.left) {
|
|
initHorizontalGlyphQuads(leftJustifiedGlyphQuads, shapedTextOrientations.left);
|
|
}
|
|
|
|
if (shapedTextOrientations.vertical) {
|
|
verticalGlyphQuads = getGlyphQuads(
|
|
shapedTextOrientations.vertical, textOffset, layout, textPlacement, imageMap, allowVerticalPlacement);
|
|
}
|
|
}
|
|
|
|
bool SymbolInstanceSharedData::empty() const {
|
|
return rightJustifiedGlyphQuads.empty() && centerJustifiedGlyphQuads.empty() && leftJustifiedGlyphQuads.empty() &&
|
|
verticalGlyphQuads.empty();
|
|
}
|
|
|
|
SymbolInstance::SymbolInstance(Anchor& anchor_,
|
|
std::shared_ptr<SymbolInstanceSharedData> sharedData_,
|
|
const ShapedTextOrientations& shapedTextOrientations,
|
|
const std::optional<PositionedIcon>& shapedIcon,
|
|
const std::optional<PositionedIcon>& verticallyShapedIcon,
|
|
const float textBoxScale_,
|
|
const float textPadding,
|
|
const SymbolPlacementType textPlacement,
|
|
const std::array<float, 2>& textOffset_,
|
|
const float iconBoxScale,
|
|
const float iconPadding,
|
|
const std::array<float, 2>& iconOffset_,
|
|
const RefIndexedSubfeature& indexedFeature,
|
|
const std::size_t layoutFeatureIndex_,
|
|
const std::size_t dataFeatureIndex_,
|
|
std::u16string key_,
|
|
const float overscaling,
|
|
const float iconRotation,
|
|
const float textRotation,
|
|
const std::array<float, 2>& variableTextOffset_,
|
|
bool allowVerticalPlacement,
|
|
const SymbolContent iconType)
|
|
: sharedData(std::move(sharedData_)),
|
|
anchor(anchor_),
|
|
symbolContent(iconType),
|
|
// Create the collision features that will be used to check whether this
|
|
// symbol instance can be placed As a collision approximation, we can use
|
|
// either the vertical or any of the horizontal versions of the feature
|
|
textCollisionFeature(sharedData->line,
|
|
anchor,
|
|
getAnyShaping(shapedTextOrientations),
|
|
textBoxScale_,
|
|
textPadding,
|
|
textPlacement,
|
|
indexedFeature,
|
|
overscaling,
|
|
textRotation),
|
|
iconCollisionFeature(
|
|
sharedData->line, anchor, shapedIcon, iconBoxScale, iconPadding, indexedFeature, iconRotation),
|
|
writingModes(WritingModeType::None),
|
|
layoutFeatureIndex(layoutFeatureIndex_),
|
|
dataFeatureIndex(dataFeatureIndex_),
|
|
textOffset(textOffset_),
|
|
iconOffset(iconOffset_),
|
|
key(std::move(key_)),
|
|
textBoxScale(textBoxScale_),
|
|
variableTextOffset(variableTextOffset_),
|
|
singleLine(shapedTextOrientations.singleLine) {
|
|
// 'hasText' depends on finding at least one glyph in the shaping that's also in the GlyphPositionMap
|
|
if (!sharedData->empty()) symbolContent |= SymbolContent::Text;
|
|
if (allowVerticalPlacement && shapedTextOrientations.vertical) {
|
|
const float verticalPointLabelAngle = 90.0f;
|
|
verticalTextCollisionFeature = CollisionFeature(line(),
|
|
anchor,
|
|
shapedTextOrientations.vertical,
|
|
textBoxScale_,
|
|
textPadding,
|
|
textPlacement,
|
|
indexedFeature,
|
|
overscaling,
|
|
textRotation + verticalPointLabelAngle);
|
|
if (verticallyShapedIcon) {
|
|
verticalIconCollisionFeature = CollisionFeature(sharedData->line,
|
|
anchor,
|
|
verticallyShapedIcon,
|
|
iconBoxScale,
|
|
iconPadding,
|
|
indexedFeature,
|
|
iconRotation + verticalPointLabelAngle);
|
|
}
|
|
}
|
|
|
|
rightJustifiedGlyphQuadsSize = sharedData->rightJustifiedGlyphQuads.size();
|
|
centerJustifiedGlyphQuadsSize = sharedData->centerJustifiedGlyphQuads.size();
|
|
leftJustifiedGlyphQuadsSize = sharedData->leftJustifiedGlyphQuads.size();
|
|
verticalGlyphQuadsSize = sharedData->verticalGlyphQuads.size();
|
|
iconQuadsSize = sharedData->iconQuads ? sharedData->iconQuads->size() : 0;
|
|
|
|
if (rightJustifiedGlyphQuadsSize || centerJustifiedGlyphQuadsSize || leftJustifiedGlyphQuadsSize) {
|
|
writingModes |= WritingModeType::Horizontal;
|
|
}
|
|
|
|
if (verticalGlyphQuadsSize) {
|
|
writingModes |= WritingModeType::Vertical;
|
|
}
|
|
}
|
|
|
|
const GeometryCoordinates& SymbolInstance::line() const {
|
|
assert(sharedData);
|
|
return sharedData->line;
|
|
}
|
|
|
|
const SymbolQuads& SymbolInstance::rightJustifiedGlyphQuads() const {
|
|
assert(sharedData);
|
|
return sharedData->rightJustifiedGlyphQuads;
|
|
}
|
|
|
|
const SymbolQuads& SymbolInstance::leftJustifiedGlyphQuads() const {
|
|
assert(sharedData);
|
|
return sharedData->leftJustifiedGlyphQuads;
|
|
}
|
|
|
|
const SymbolQuads& SymbolInstance::centerJustifiedGlyphQuads() const {
|
|
assert(sharedData);
|
|
return sharedData->centerJustifiedGlyphQuads;
|
|
}
|
|
|
|
const SymbolQuads& SymbolInstance::verticalGlyphQuads() const {
|
|
assert(sharedData);
|
|
return sharedData->verticalGlyphQuads;
|
|
}
|
|
|
|
const std::optional<SymbolQuads>& SymbolInstance::iconQuads() const {
|
|
assert(sharedData);
|
|
return sharedData->iconQuads;
|
|
}
|
|
|
|
bool SymbolInstance::hasText() const {
|
|
return static_cast<bool>(symbolContent & SymbolContent::Text);
|
|
}
|
|
|
|
bool SymbolInstance::hasIcon() const {
|
|
return static_cast<bool>(symbolContent & SymbolContent::IconRGBA) || hasSdfIcon();
|
|
}
|
|
|
|
bool SymbolInstance::hasSdfIcon() const {
|
|
return static_cast<bool>(symbolContent & SymbolContent::IconSDF);
|
|
}
|
|
|
|
const std::optional<SymbolQuads>& SymbolInstance::verticalIconQuads() const {
|
|
assert(sharedData);
|
|
return sharedData->verticalIconQuads;
|
|
}
|
|
|
|
void SymbolInstance::releaseSharedData() {
|
|
sharedData.reset();
|
|
}
|
|
|
|
std::optional<size_t> SymbolInstance::getDefaultHorizontalPlacedTextIndex() const {
|
|
if (placedRightTextIndex) return placedRightTextIndex;
|
|
if (placedCenterTextIndex) return placedCenterTextIndex;
|
|
if (placedLeftTextIndex) return placedLeftTextIndex;
|
|
return std::nullopt;
|
|
}
|
|
} // namespace mbgl
|