[core] Release quad data after vertex buffers are created

This commit is contained in:
Alexander Shalamov
2019-07-21 12:16:02 +03:00
parent dabf5d0c3a
commit ac74fc6d00
5 changed files with 184 additions and 101 deletions

View File

@@ -18,55 +18,22 @@ const Shaping& getAnyShaping(const ShapedTextOrientations& shapedTextOrientation
} // namespace
SymbolInstance::SymbolInstance(Anchor& anchor_,
GeometryCoordinates line_,
const ShapedTextOrientations& shapedTextOrientations,
optional<PositionedIcon> shapedIcon,
const SymbolLayoutProperties::Evaluated& layout,
const float layoutTextSize,
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 GlyphPositions& positions,
const IndexedSubfeature& indexedFeature,
const std::size_t layoutFeatureIndex_,
const std::size_t dataFeatureIndex_,
std::u16string key_,
const float overscaling,
const float rotate,
float radialTextOffset_) :
anchor(anchor_),
line(line_),
hasText(false),
hasIcon(shapedIcon),
// 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(line_, anchor, getAnyShaping(shapedTextOrientations), textBoxScale_, textPadding, textPlacement, indexedFeature, overscaling, rotate),
iconCollisionFeature(line_, anchor, shapedIcon, iconBoxScale, iconPadding, indexedFeature, rotate),
writingModes(WritingModeType::None),
layoutFeatureIndex(layoutFeatureIndex_),
dataFeatureIndex(dataFeatureIndex_),
textOffset(textOffset_),
iconOffset(iconOffset_),
key(std::move(key_)),
textBoxScale(textBoxScale_),
radialTextOffset(radialTextOffset_),
singleLine(shapedTextOrientations.singleLine) {
SymbolInstanceSharedData::SymbolInstanceSharedData(GeometryCoordinates line_,
const ShapedTextOrientations& shapedTextOrientations,
const optional<PositionedIcon>& shapedIcon,
const style::SymbolLayoutProperties::Evaluated& layout,
const float layoutTextSize,
const style::SymbolPlacementType textPlacement,
const std::array<float, 2>& textOffset,
const GlyphPositions& positions) : line(std::move(line_)) {
// Create the quads used for rendering the icon and glyphs.
if (shapedIcon) {
iconQuad = getIconQuad(*shapedIcon, layout, layoutTextSize, shapedTextOrientations.horizontal);
}
bool singleLineInitialized = false;
const auto initHorizontalGlyphQuads = [&] (SymbolQuads& quads, const Shaping& shaping) {
writingModes |= WritingModeType::Horizontal;
if (!singleLine) {
if (!shapedTextOrientations.singleLine) {
quads = getGlyphQuads(shaping, textOffset, layout, textPlacement, positions);
return;
}
@@ -75,7 +42,7 @@ SymbolInstance::SymbolInstance(Anchor& anchor_,
singleLineInitialized = true;
}
};
if (shapedTextOrientations.right) {
initHorizontalGlyphQuads(rightJustifiedGlyphQuads, shapedTextOrientations.right);
}
@@ -89,12 +56,97 @@ SymbolInstance::SymbolInstance(Anchor& anchor_,
}
if (shapedTextOrientations.vertical) {
writingModes |= WritingModeType::Vertical;
verticalGlyphQuads = getGlyphQuads(shapedTextOrientations.vertical, textOffset, layout, textPlacement, positions);
}
}
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 optional<PositionedIcon>& shapedIcon,
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 IndexedSubfeature& indexedFeature,
const std::size_t layoutFeatureIndex_,
const std::size_t dataFeatureIndex_,
std::u16string key_,
const float overscaling,
const float rotate,
float radialTextOffset_) :
sharedData(std::move(sharedData_)),
anchor(anchor_),
// 'hasText' depends on finding at least one glyph in the shaping that's also in the GlyphPositionMap
hasText = !rightJustifiedGlyphQuads.empty() || !centerJustifiedGlyphQuads.empty() || !leftJustifiedGlyphQuads.empty() || !verticalGlyphQuads.empty();
hasText(!sharedData->empty()),
hasIcon(shapedIcon),
// 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, rotate),
iconCollisionFeature(sharedData->line, anchor, shapedIcon, iconBoxScale, iconPadding, indexedFeature, rotate),
writingModes(WritingModeType::None),
layoutFeatureIndex(layoutFeatureIndex_),
dataFeatureIndex(dataFeatureIndex_),
textOffset(textOffset_),
iconOffset(iconOffset_),
key(std::move(key_)),
textBoxScale(textBoxScale_),
radialTextOffset(radialTextOffset_),
singleLine(shapedTextOrientations.singleLine) {
rightJustifiedGlyphQuadsSize = sharedData->rightJustifiedGlyphQuads.size();
centerJustifiedGlyphQuadsSize = sharedData->centerJustifiedGlyphQuads.size();
leftJustifiedGlyphQuadsSize = sharedData->leftJustifiedGlyphQuads.size();
verticalGlyphQuadsSize = sharedData->verticalGlyphQuads.size();
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 optional<SymbolQuad>& SymbolInstance::iconQuad() const {
assert(sharedData);
return sharedData->iconQuad;
}
void SymbolInstance::releaseSharedData() {
sharedData.reset();
}
optional<size_t> SymbolInstance::getDefaultHorizontalPlacedTextIndex() const {

View File

@@ -21,23 +21,39 @@ struct ShapedTextOrientations {
bool singleLine = false;
};
struct SymbolInstanceSharedData {
SymbolInstanceSharedData(GeometryCoordinates line,
const ShapedTextOrientations& shapedTextOrientations,
const optional<PositionedIcon>& shapedIcon,
const style::SymbolLayoutProperties::Evaluated& layout,
const float layoutTextSize,
const style::SymbolPlacementType textPlacement,
const std::array<float, 2>& textOffset,
const GlyphPositions& positions);
bool empty() const;
GeometryCoordinates line;
// Note: When singleLine == true, only `rightJustifiedGlyphQuads` is populated.
SymbolQuads rightJustifiedGlyphQuads;
SymbolQuads centerJustifiedGlyphQuads;
SymbolQuads leftJustifiedGlyphQuads;
SymbolQuads verticalGlyphQuads;
optional<SymbolQuad> iconQuad;
};
class SymbolInstance {
public:
SymbolInstance(Anchor& anchor,
GeometryCoordinates line,
SymbolInstance(Anchor& anchor_,
std::shared_ptr<SymbolInstanceSharedData> sharedData,
const ShapedTextOrientations& shapedTextOrientations,
optional<PositionedIcon> shapedIcon,
const style::SymbolLayoutProperties::Evaluated&,
const float layoutTextSize,
const optional<PositionedIcon>& shapedIcon,
const float textBoxScale,
const float textPadding,
style::SymbolPlacementType textPlacement,
const std::array<float, 2> textOffset,
const style::SymbolPlacementType textPlacement,
const std::array<float, 2>& textOffset,
const float iconBoxScale,
const float iconPadding,
const std::array<float, 2> iconOffset,
const GlyphPositions&,
const IndexedSubfeature&,
const std::array<float, 2>& iconOffset,
const IndexedSubfeature& indexedFeature,
const std::size_t layoutFeatureIndex,
const std::size_t dataFeatureIndex,
std::u16string key,
@@ -46,18 +62,27 @@ public:
float radialTextOffset);
optional<size_t> getDefaultHorizontalPlacedTextIndex() const;
const GeometryCoordinates& line() const;
const SymbolQuads& rightJustifiedGlyphQuads() const;
const SymbolQuads& leftJustifiedGlyphQuads() const;
const SymbolQuads& centerJustifiedGlyphQuads() const;
const SymbolQuads& verticalGlyphQuads() const;
const optional<SymbolQuad>& iconQuad() const;
void releaseSharedData();
private:
std::shared_ptr<SymbolInstanceSharedData> sharedData;
public:
Anchor anchor;
GeometryCoordinates line;
bool hasText;
bool hasIcon;
// Note: When singleLine == true, only `rightJustifiedGlyphQuads` is populated.
SymbolQuads rightJustifiedGlyphQuads;
SymbolQuads centerJustifiedGlyphQuads;
SymbolQuads leftJustifiedGlyphQuads;
SymbolQuads verticalGlyphQuads;
std::size_t rightJustifiedGlyphQuadsSize;
std::size_t centerJustifiedGlyphQuadsSize;
std::size_t leftJustifiedGlyphQuadsSize;
std::size_t verticalGlyphQuadsSize;
optional<SymbolQuad> iconQuad;
CollisionFeature textCollisionFeature;
CollisionFeature iconCollisionFeature;
WritingModeType writingModes;

View File

@@ -397,7 +397,7 @@ void SymbolLayout::prepareSymbols(const GlyphMap& glyphMap, const GlyphPositions
void SymbolLayout::addFeature(const std::size_t layoutFeatureIndex,
const SymbolFeature& feature,
const ShapedTextOrientations& shapedTextOrientations,
optional<PositionedIcon> shapedIcon,
const optional<PositionedIcon>& shapedIcon,
const GlyphPositions& glyphPositions,
Point<float> offset) {
const float minScale = 0.5f;
@@ -433,7 +433,8 @@ void SymbolLayout::addFeature(const std::size_t layoutFeatureIndex,
const auto evaluatedLayoutProperties = layout->evaluate(zoom, feature);
IndexedSubfeature indexedFeature(feature.index, sourceLayer->getName(), bucketLeaderID, symbolInstances.size());
auto addSymbolInstance = [&] (const GeometryCoordinates& line, Anchor& anchor) {
auto addSymbolInstance = [&] (Anchor& anchor, std::shared_ptr<SymbolInstanceSharedData> sharedData) {
assert(sharedData);
const bool anchorInsideTile = anchor.point.x >= 0 && anchor.point.x < util::EXTENT && anchor.point.y >= 0 && anchor.point.y < util::EXTENT;
if (mode == MapMode::Tile || anchorInsideTile) {
@@ -442,20 +443,26 @@ void SymbolLayout::addFeature(const std::size_t layoutFeatureIndex,
// In tiled rendering mode, add all symbols in the buffers so that we can:
// (1) render symbols that overlap into this tile
// (2) approximate collision detection effects from neighboring symbols
symbolInstances.emplace_back(anchor, line, shapedTextOrientations, shapedIcon,
evaluatedLayoutProperties, layoutTextSize,
symbolInstances.emplace_back(anchor, std::move(sharedData), shapedTextOrientations, shapedIcon,
textBoxScale, textPadding, textPlacement, textOffset,
iconBoxScale, iconPadding, iconOffset,
glyphPositions, indexedFeature, layoutFeatureIndex, feature.index,
feature.formattedText ? feature.formattedText->rawText() : std::u16string(), overscaling, rotation, radialTextOffset);
iconBoxScale, iconPadding, iconOffset, indexedFeature,
layoutFeatureIndex, feature.index,
feature.formattedText ? feature.formattedText->rawText() : std::u16string(),
overscaling, rotation, radialTextOffset);
}
};
const auto createSymbolInstanceSharedData = [&] (GeometryCoordinates line) {
return std::make_shared<SymbolInstanceSharedData>(std::move(line),
shapedTextOrientations, shapedIcon, evaluatedLayoutProperties, layoutTextSize,
textPlacement, textOffset, glyphPositions);
};
const auto& type = feature.getType();
if (layout->get<SymbolPlacement>() == SymbolPlacementType::Line) {
auto clippedLines = util::clipLines(feature.geometry, 0, 0, util::EXTENT, util::EXTENT);
for (const auto& line : clippedLines) {
for (auto& line : clippedLines) {
Anchors anchors = getAnchors(line,
symbolSpacing,
textMaxAngle,
@@ -466,10 +473,10 @@ void SymbolLayout::addFeature(const std::size_t layoutFeatureIndex,
glyphSize,
textMaxBoxScale,
overscaling);
auto sharedData = createSymbolInstanceSharedData(std::move(line));
for (auto& anchor : anchors) {
if (!feature.formattedText || !anchorIsTooClose(feature.formattedText->rawText(), textRepeatDistance, anchor)) {
addSymbolInstance(line, anchor);
addSymbolInstance(anchor, sharedData);
}
}
}
@@ -487,7 +494,7 @@ void SymbolLayout::addFeature(const std::size_t layoutFeatureIndex,
glyphSize,
textMaxBoxScale);
if (anchor) {
addSymbolInstance(line, *anchor);
addSymbolInstance(*anchor, createSymbolInstanceSharedData(line));
}
}
}
@@ -505,18 +512,18 @@ void SymbolLayout::addFeature(const std::size_t layoutFeatureIndex,
// 1 pixel worth of precision, in tile coordinates
auto poi = mapbox::polylabel(poly, double(util::EXTENT / util::tileSize));
Anchor anchor(poi.x, poi.y, 0, minScale);
addSymbolInstance(polygon[0], anchor);
addSymbolInstance(anchor, createSymbolInstanceSharedData(polygon[0]));
}
} else if (type == FeatureType::LineString) {
for (const auto& line : feature.geometry) {
Anchor anchor(line[0].x, line[0].y, 0, minScale);
addSymbolInstance(line, anchor);
addSymbolInstance(anchor, createSymbolInstanceSharedData(line));
}
} else if (type == FeatureType::Point) {
for (const auto& points : feature.geometry) {
for (const auto& point : points) {
Anchor anchor(point.x, point.y, 0, minScale);
addSymbolInstance({point}, anchor);
addSymbolInstance(anchor, createSymbolInstanceSharedData({point}));
}
}
}
@@ -576,36 +583,36 @@ void SymbolLayout::createBucket(const ImagePositions&, std::unique_ptr<FeatureIn
optional<std::size_t> lastAddedSection;
if (singleLine) {
optional<std::size_t> placedTextIndex;
lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, placedTextIndex, symbolInstance.rightJustifiedGlyphQuads, lastAddedSection);
lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, placedTextIndex, symbolInstance.rightJustifiedGlyphQuads(), lastAddedSection);
symbolInstance.placedRightTextIndex = placedTextIndex;
symbolInstance.placedCenterTextIndex = placedTextIndex;
symbolInstance.placedLeftTextIndex = placedTextIndex;
} else {
if (!symbolInstance.rightJustifiedGlyphQuads.empty()) {
lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, symbolInstance.placedRightTextIndex, symbolInstance.rightJustifiedGlyphQuads, lastAddedSection);
if (symbolInstance.rightJustifiedGlyphQuadsSize) {
lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, symbolInstance.placedRightTextIndex, symbolInstance.rightJustifiedGlyphQuads(), lastAddedSection);
}
if (!symbolInstance.centerJustifiedGlyphQuads.empty()) {
lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, symbolInstance.placedCenterTextIndex, symbolInstance.centerJustifiedGlyphQuads, lastAddedSection);
if (symbolInstance.centerJustifiedGlyphQuadsSize) {
lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, symbolInstance.placedCenterTextIndex, symbolInstance.centerJustifiedGlyphQuads(), lastAddedSection);
}
if (!symbolInstance.leftJustifiedGlyphQuads.empty()) {
lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, symbolInstance.placedLeftTextIndex, symbolInstance.leftJustifiedGlyphQuads, lastAddedSection);
if (symbolInstance.leftJustifiedGlyphQuadsSize) {
lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, symbolInstance.placedLeftTextIndex, symbolInstance.leftJustifiedGlyphQuads(), lastAddedSection);
}
}
if (symbolInstance.writingModes & WritingModeType::Vertical) {
lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, WritingModeType::Vertical, symbolInstance.placedVerticalTextIndex, symbolInstance.verticalGlyphQuads, lastAddedSection);
if (symbolInstance.writingModes & WritingModeType::Vertical && symbolInstance.verticalGlyphQuadsSize) {
lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, WritingModeType::Vertical, symbolInstance.placedVerticalTextIndex, symbolInstance.verticalGlyphQuads(), lastAddedSection);
}
assert(lastAddedSection); // True, as hasText == true;
updatePaintPropertiesForSection(*bucket, feature, *lastAddedSection);
}
if (hasIcon) {
if (symbolInstance.iconQuad) {
if (symbolInstance.hasIcon) {
const Range<float> sizeData = bucket->iconSizeBinder->getVertexSizeData(feature);
bucket->icon.placedSymbols.emplace_back(symbolInstance.anchor.point, symbolInstance.anchor.segment, sizeData.min, sizeData.max,
symbolInstance.iconOffset, WritingModeType::None, symbolInstance.line, std::vector<float>());
symbolInstance.iconOffset, WritingModeType::None, symbolInstance.line(), std::vector<float>());
symbolInstance.placedIconIndex = bucket->icon.placedSymbols.size() - 1;
PlacedSymbol& iconSymbol = bucket->icon.placedSymbols.back();
iconSymbol.vertexStartIndex = addSymbol(bucket->icon, sizeData, *symbolInstance.iconQuad,
iconSymbol.vertexStartIndex = addSymbol(bucket->icon, sizeData, *symbolInstance.iconQuad(),
symbolInstance.anchor, iconSymbol, feature.sortKey);
for (auto& pair : bucket->paintProperties) {
@@ -613,6 +620,7 @@ void SymbolLayout::createBucket(const ImagePositions&, std::unique_ptr<FeatureIn
}
}
}
symbolInstance.releaseSharedData();
}
if (showCollisionBoxes) {
@@ -649,7 +657,7 @@ std::size_t SymbolLayout::addSymbolGlyphQuads(SymbolBucket& bucket,
const bool hasFormatSectionOverrides = bucket.hasFormatSectionOverrides();
bucket.text.placedSymbols.emplace_back(symbolInstance.anchor.point, symbolInstance.anchor.segment, sizeData.min, sizeData.max,
symbolInstance.textOffset, writingMode, symbolInstance.line, CalculateTileDistances(symbolInstance.line, symbolInstance.anchor));
symbolInstance.textOffset, writingMode, symbolInstance.line(), CalculateTileDistances(symbolInstance.line(), symbolInstance.anchor));
placedIndex = bucket.text.placedSymbols.size() - 1;
PlacedSymbol& placedSymbol = bucket.text.placedSymbols.back();

View File

@@ -51,7 +51,7 @@ private:
void addFeature(const size_t,
const SymbolFeature&,
const ShapedTextOrientations& shapedTextOrientations,
optional<PositionedIcon> shapedIcon,
const optional<PositionedIcon>& shapedIcon,
const GlyphPositions&,
Point<float> textOffset);

View File

@@ -547,28 +547,28 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, const TransformState
if (symbolInstance.hasText) {
auto opacityVertex = SymbolSDFTextProgram::opacityVertex(opacityState.text.placed, opacityState.text.opacity);
if (symbolInstance.placedRightTextIndex) {
for (size_t i = 0; i < symbolInstance.rightJustifiedGlyphQuads.size() * 4; i++) {
for (size_t i = 0; i < symbolInstance.rightJustifiedGlyphQuadsSize * 4; i++) {
bucket.text.opacityVertices.emplace_back(opacityVertex);
}
PlacedSymbol& placed = bucket.text.placedSymbols[*symbolInstance.placedRightTextIndex];
placed.hidden = opacityState.isHidden();
}
if (symbolInstance.placedCenterTextIndex && !symbolInstance.singleLine) {
for (size_t i = 0; i < symbolInstance.centerJustifiedGlyphQuads.size() * 4; i++) {
for (size_t i = 0; i < symbolInstance.centerJustifiedGlyphQuadsSize * 4; i++) {
bucket.text.opacityVertices.emplace_back(opacityVertex);
}
PlacedSymbol& placed = bucket.text.placedSymbols[*symbolInstance.placedCenterTextIndex];
placed.hidden = opacityState.isHidden();
}
if (symbolInstance.placedLeftTextIndex && !symbolInstance.singleLine) {
for (size_t i = 0; i < symbolInstance.leftJustifiedGlyphQuads.size() * 4; i++) {
for (size_t i = 0; i < symbolInstance.leftJustifiedGlyphQuadsSize * 4; i++) {
bucket.text.opacityVertices.emplace_back(opacityVertex);
}
PlacedSymbol& placed = bucket.text.placedSymbols[*symbolInstance.placedLeftTextIndex];
placed.hidden = opacityState.isHidden();
}
if (symbolInstance.placedVerticalTextIndex) {
for (size_t i = 0; i < symbolInstance.verticalGlyphQuads.size() * 4; i++) {
for (size_t i = 0; i < symbolInstance.verticalGlyphQuadsSize * 4; i++) {
bucket.text.opacityVertices.emplace_back(opacityVertex);
}
bucket.text.placedSymbols[*symbolInstance.placedVerticalTextIndex].hidden = opacityState.isHidden();
@@ -581,12 +581,10 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, const TransformState
}
if (symbolInstance.hasIcon) {
auto opacityVertex = SymbolIconProgram::opacityVertex(opacityState.icon.placed, opacityState.icon.opacity);
if (symbolInstance.iconQuad) {
bucket.icon.opacityVertices.emplace_back(opacityVertex);
bucket.icon.opacityVertices.emplace_back(opacityVertex);
bucket.icon.opacityVertices.emplace_back(opacityVertex);
bucket.icon.opacityVertices.emplace_back(opacityVertex);
}
bucket.icon.opacityVertices.emplace_back(opacityVertex);
bucket.icon.opacityVertices.emplace_back(opacityVertex);
bucket.icon.opacityVertices.emplace_back(opacityVertex);
bucket.icon.opacityVertices.emplace_back(opacityVertex);
if (symbolInstance.placedIconIndex) {
bucket.icon.placedSymbols[*symbolInstance.placedIconIndex].hidden = opacityState.isHidden();
}