void OsmAnd::MapRasterizer_P::rasterizePolylineIcons( const Context& context, SkCanvas& canvas, const SkPath& path, const MapStyleEvaluationResult& evalResult) { bool ok; QString pathIconName; ok = evalResult.getStringValue(context.env->styleBuiltinValueDefs->id_OUTPUT_PATH_ICON, pathIconName); if (!ok || pathIconName.isEmpty()) return; float pathIconStep = 0.0f; ok = evalResult.getFloatValue(context.env->styleBuiltinValueDefs->id_OUTPUT_PATH_ICON_STEP, pathIconStep); if (!ok || pathIconStep <= 0.0f) return; std::shared_ptr<const SkBitmap> pathIcon; ok = context.env->obtainMapIcon(pathIconName, pathIcon); if (!ok || !pathIcon) return; SkMatrix mIconTransform; mIconTransform.setIdentity(); mIconTransform.setTranslate(-0.5f * pathIcon->width(), -0.5f * pathIcon->height()); mIconTransform.postRotate(90.0f); SkPathMeasure pathMeasure(path, false); const auto length = pathMeasure.getLength(); auto iconOffset = 0.5f * pathIconStep; const auto iconInstancesCount = static_cast<int>((length - iconOffset) / pathIconStep) + 1; if (iconInstancesCount < 1) return; SkMatrix mIconInstanceTransform; for (auto iconInstanceIdx = 0; iconInstanceIdx < iconInstancesCount; iconInstanceIdx++, iconOffset += pathIconStep) { SkMatrix mPinPoint; ok = pathMeasure.getMatrix(iconOffset, &mPinPoint); if (!ok) break; mIconInstanceTransform.setConcat(mPinPoint, mIconTransform); canvas.save(); canvas.concat(mIconInstanceTransform); canvas.drawBitmap(*pathIcon, 0, 0, &_defaultPaint); canvas.restore(); } }
unsigned int OsmAnd::MapPresentationEnvironment_P::getRoadsDensityLimitPerTile(const ZoomLevel zoom) const { auto result = _roadsDensityLimitPerTile; if (_roadsDensityLimitPerTileAttribute) { MapStyleEvaluator evaluator(owner->resolvedStyle, owner->displayDensityFactor * owner->mapScaleFactor); applyTo(evaluator); evaluator.setIntegerValue(owner->styleBuiltinValueDefs->id_INPUT_MINZOOM, zoom); MapStyleEvaluationResult evalResult; if (evaluator.evaluate(_roadsDensityLimitPerTileAttribute, &evalResult)) evalResult.getIntegerValue(owner->styleBuiltinValueDefs->id_OUTPUT_ATTR_INT_VALUE, result); } return result; }
OsmAnd::ColorARGB OsmAnd::MapPresentationEnvironment_P::getDefaultBackgroundColor(const ZoomLevel zoom) const { auto result = _defaultBackgroundColor; if (_defaultBackgroundColorAttribute) { MapStyleEvaluator evaluator(owner->resolvedStyle, owner->displayDensityFactor * owner->mapScaleFactor); applyTo(evaluator); evaluator.setIntegerValue(owner->styleBuiltinValueDefs->id_INPUT_MINZOOM, zoom); MapStyleEvaluationResult evalResult; if (evaluator.evaluate(_defaultBackgroundColorAttribute, &evalResult)) evalResult.getIntegerValue(owner->styleBuiltinValueDefs->id_OUTPUT_ATTR_COLOR_VALUE, result.argb); } return result; }
void OsmAnd::MapPresentationEnvironment_P::obtainShadowRenderingOptions(const ZoomLevel zoom, int& mode, ColorARGB& color) const { mode = _shadowRenderingMode; color = _shadowRenderingColor; if (_attributeRule_shadowRendering) { MapStyleEvaluator evaluator(owner->style, owner->displayDensityFactor); applyTo(evaluator); evaluator.setIntegerValue(owner->styleBuiltinValueDefs->id_INPUT_MINZOOM, zoom); MapStyleEvaluationResult evalResult; if (evaluator.evaluate(_attributeRule_shadowRendering, &evalResult)) { evalResult.getIntegerValue(owner->styleBuiltinValueDefs->id_OUTPUT_ATTR_INT_VALUE, mode); evalResult.getIntegerValue(owner->styleBuiltinValueDefs->id_OUTPUT_SHADOW_COLOR, color.argb); } } }
float OsmAnd::MapPresentationEnvironment_P::getGlobalPathPadding() const { auto result = _globalPathPadding; if (_globalPathPaddingAttribute) { MapStyleEvaluator evaluator(owner->resolvedStyle, owner->displayDensityFactor * owner->symbolsScaleFactor); applyTo(evaluator); MapStyleEvaluationResult evalResult; if (evaluator.evaluate(_globalPathPaddingAttribute, &evalResult)) { float value = 0.0f; if (evalResult.getFloatValue(owner->styleBuiltinValueDefs->id_OUTPUT_ATTR_FLOAT_VALUE, value)) result = value; } } return result; }
void OsmAnd::MapStyleEvaluator_P::postprocessEvaluationResult( const MapObject* const mapObject, const std::shared_ptr<const InputValues>& inputValues, const IntermediateEvaluationResult& intermediateResult, MapStyleEvaluationResult& outResultStorage, OnDemand<IntermediateEvaluationResult>& constantEvaluationResult) const { IMapStyle::Value value; for (IntermediateEvaluationResult::KeyType idx = 0, count = intermediateResult.size(); idx < count; idx++) { if (!intermediateResult.get(idx, value)) continue; const auto valueDefId = static_cast<IMapStyle::ValueDefinitionId>(idx); const auto& valueDef = owner->mapStyle->getValueDefinitionRefById(valueDefId); const auto constantRuleValue = evaluateConstantValue( mapObject, valueDef->dataType, value, inputValues, constantEvaluationResult); QVariant postprocessedValue; switch (valueDef->dataType) { case MapStyleValueDataType::Boolean: assert(!constantRuleValue.isComplex); postprocessedValue = (constantRuleValue.asSimple.asUInt != 0); break; case MapStyleValueDataType::Integer: postprocessedValue = constantRuleValue.isComplex ? constantRuleValue.asComplex.asInt.evaluate(owner->ptScaleFactor) : constantRuleValue.asSimple.asInt; break; case MapStyleValueDataType::Float: postprocessedValue = constantRuleValue.isComplex ? constantRuleValue.asComplex.asFloat.evaluate(owner->ptScaleFactor) : constantRuleValue.asSimple.asFloat; break; case MapStyleValueDataType::String: assert(!constantRuleValue.isComplex); // Save value of a string instead of it's id postprocessedValue = owner->mapStyle->getStringById(constantRuleValue.asSimple.asUInt); break; case MapStyleValueDataType::Color: assert(!constantRuleValue.isComplex); postprocessedValue = constantRuleValue.asSimple.asUInt; break; } outResultStorage.setValue(valueDefId, postprocessedValue); } }
double OsmAnd::MapPresentationEnvironment_P::getPolygonAreaMinimalThreshold(const ZoomLevel zoom) const { auto result = _polygonMinSizeToDisplay; if (_polygonMinSizeToDisplayAttribute) { MapStyleEvaluator evaluator(owner->resolvedStyle, owner->displayDensityFactor * owner->mapScaleFactor); applyTo(evaluator); evaluator.setIntegerValue(owner->styleBuiltinValueDefs->id_INPUT_MINZOOM, zoom); MapStyleEvaluationResult evalResult; if (evaluator.evaluate(_polygonMinSizeToDisplayAttribute, &evalResult)) { int polygonMinSizeToDisplay; if (evalResult.getIntegerValue(owner->styleBuiltinValueDefs->id_OUTPUT_ATTR_INT_VALUE, polygonMinSizeToDisplay)) result = polygonMinSizeToDisplay; } } return result; }
void OsmAnd::MapPresentationEnvironment_P::obtainShadowOptions(const ZoomLevel zoom, ShadowMode& mode, ColorARGB& color) const { bool ok; mode = _shadowMode; color = _shadowColor; if (_shadowOptionsAttribute) { MapStyleEvaluator evaluator(owner->resolvedStyle, owner->displayDensityFactor * owner->mapScaleFactor); applyTo(evaluator); evaluator.setIntegerValue(owner->styleBuiltinValueDefs->id_INPUT_MINZOOM, zoom); MapStyleEvaluationResult evalResult; if (evaluator.evaluate(_shadowOptionsAttribute, &evalResult)) { int modeValue = 0; ok = evalResult.getIntegerValue(owner->styleBuiltinValueDefs->id_OUTPUT_ATTR_INT_VALUE, modeValue); if (ok) mode = static_cast<ShadowMode>(modeValue); evalResult.getIntegerValue(owner->styleBuiltinValueDefs->id_OUTPUT_SHADOW_COLOR, color.argb); } } }
bool OsmAnd::MapRasterizer_P::updatePaint( const Context& context, SkPaint& paint, const MapStyleEvaluationResult& evalResult, const PaintValuesSet valueSetSelector, const bool isArea) { const auto& env = context.env; bool ok = true; int valueDefId_color = -1; int valueDefId_strokeWidth = -1; int valueDefId_cap = -1; int valueDefId_pathEffect = -1; switch (valueSetSelector) { case PaintValuesSet::Layer_minus2: valueDefId_color = env->styleBuiltinValueDefs->id_OUTPUT_COLOR__2; valueDefId_strokeWidth = env->styleBuiltinValueDefs->id_OUTPUT_STROKE_WIDTH__2; valueDefId_cap = env->styleBuiltinValueDefs->id_OUTPUT_CAP__2; valueDefId_pathEffect = env->styleBuiltinValueDefs->id_OUTPUT_PATH_EFFECT__2; break; case PaintValuesSet::Layer_minus1: valueDefId_color = env->styleBuiltinValueDefs->id_OUTPUT_COLOR__1; valueDefId_strokeWidth = env->styleBuiltinValueDefs->id_OUTPUT_STROKE_WIDTH__1; valueDefId_cap = env->styleBuiltinValueDefs->id_OUTPUT_CAP__1; valueDefId_pathEffect = env->styleBuiltinValueDefs->id_OUTPUT_PATH_EFFECT__1; break; case PaintValuesSet::Layer_0: valueDefId_color = env->styleBuiltinValueDefs->id_OUTPUT_COLOR_0; valueDefId_strokeWidth = env->styleBuiltinValueDefs->id_OUTPUT_STROKE_WIDTH_0; valueDefId_cap = env->styleBuiltinValueDefs->id_OUTPUT_CAP_0; valueDefId_pathEffect = env->styleBuiltinValueDefs->id_OUTPUT_PATH_EFFECT_0; break; case PaintValuesSet::Layer_1: valueDefId_color = env->styleBuiltinValueDefs->id_OUTPUT_COLOR; valueDefId_strokeWidth = env->styleBuiltinValueDefs->id_OUTPUT_STROKE_WIDTH; valueDefId_cap = env->styleBuiltinValueDefs->id_OUTPUT_CAP; valueDefId_pathEffect = env->styleBuiltinValueDefs->id_OUTPUT_PATH_EFFECT; break; case PaintValuesSet::Layer_2: valueDefId_color = env->styleBuiltinValueDefs->id_OUTPUT_COLOR_2; valueDefId_strokeWidth = env->styleBuiltinValueDefs->id_OUTPUT_STROKE_WIDTH_2; valueDefId_cap = env->styleBuiltinValueDefs->id_OUTPUT_CAP_2; valueDefId_pathEffect = env->styleBuiltinValueDefs->id_OUTPUT_PATH_EFFECT_2; break; case PaintValuesSet::Layer_3: valueDefId_color = env->styleBuiltinValueDefs->id_OUTPUT_COLOR_3; valueDefId_strokeWidth = env->styleBuiltinValueDefs->id_OUTPUT_STROKE_WIDTH_3; valueDefId_cap = env->styleBuiltinValueDefs->id_OUTPUT_CAP_3; valueDefId_pathEffect = env->styleBuiltinValueDefs->id_OUTPUT_PATH_EFFECT_3; break; case PaintValuesSet::Layer_4: valueDefId_color = env->styleBuiltinValueDefs->id_OUTPUT_COLOR_4; valueDefId_strokeWidth = env->styleBuiltinValueDefs->id_OUTPUT_STROKE_WIDTH_4; valueDefId_cap = env->styleBuiltinValueDefs->id_OUTPUT_CAP_4; valueDefId_pathEffect = env->styleBuiltinValueDefs->id_OUTPUT_PATH_EFFECT_4; break; case PaintValuesSet::Layer_5: valueDefId_color = env->styleBuiltinValueDefs->id_OUTPUT_COLOR_5; valueDefId_strokeWidth = env->styleBuiltinValueDefs->id_OUTPUT_STROKE_WIDTH_5; valueDefId_cap = env->styleBuiltinValueDefs->id_OUTPUT_CAP_5; valueDefId_pathEffect = env->styleBuiltinValueDefs->id_OUTPUT_PATH_EFFECT_5; break; default: return false; } if (isArea) { if (!evalResult.contains(valueDefId_color) && !evalResult.contains(env->styleBuiltinValueDefs->id_OUTPUT_SHADER)) return false; paint.setColorFilter(nullptr); paint.setShader(nullptr); paint.setLooper(nullptr); paint.setStyle(SkPaint::kStrokeAndFill_Style); paint.setStrokeWidth(0); } else { float stroke; ok = evalResult.getFloatValue(valueDefId_strokeWidth, stroke); if (!ok || stroke <= 0.0f) return false; paint.setColorFilter(nullptr); paint.setShader(nullptr); paint.setLooper(nullptr); paint.setStyle(SkPaint::kStroke_Style); paint.setStrokeWidth(stroke); QString cap; ok = evalResult.getStringValue(valueDefId_cap, cap); if (!ok || cap.isEmpty() || cap.compare(QLatin1String("BUTT"), Qt::CaseInsensitive) == 0) paint.setStrokeCap(SkPaint::kButt_Cap); else if (cap.compare(QLatin1String("ROUND"), Qt::CaseInsensitive) == 0) paint.setStrokeCap(SkPaint::kRound_Cap); else if (cap.compare(QLatin1String("SQUARE"), Qt::CaseInsensitive) == 0) paint.setStrokeCap(SkPaint::kSquare_Cap); else paint.setStrokeCap(SkPaint::kButt_Cap); QString encodedPathEffect; ok = evalResult.getStringValue(valueDefId_pathEffect, encodedPathEffect); if (!ok || encodedPathEffect.isEmpty()) { paint.setPathEffect(nullptr); } else { SkPathEffect* pathEffect = nullptr; ok = obtainPathEffect(encodedPathEffect, pathEffect); if (ok && pathEffect) paint.setPathEffect(pathEffect); } } SkColor color = SK_ColorTRANSPARENT; evalResult.getIntegerValue(valueDefId_color, color); paint.setColor(color); if (valueSetSelector == PaintValuesSet::Layer_1) { QString shader; ok = evalResult.getStringValue(env->styleBuiltinValueDefs->id_OUTPUT_SHADER, shader); if (ok && !shader.isEmpty()) { SkBitmapProcShader* shaderObj = nullptr; if (obtainBitmapShader(env, shader, shaderObj) && shaderObj) { // SKIA requires non-transparent color if (paint.getColor() == SK_ColorTRANSPARENT) paint.setColor(SK_ColorWHITE); paint.setShader(static_cast<SkShader*>(shaderObj))->unref(); } } } // do not check shadow color here if (context.shadowMode == MapPresentationEnvironment::ShadowMode::OneStep && valueSetSelector == PaintValuesSet::Layer_1) { ColorARGB shadowColor(0x00000000); ok = evalResult.getIntegerValue(env->styleBuiltinValueDefs->id_OUTPUT_SHADOW_COLOR, shadowColor.argb); if (!ok || shadowColor.isTransparent()) shadowColor = context.shadowColor; float shadowRadius = 0.0f; evalResult.getFloatValue(env->styleBuiltinValueDefs->id_OUTPUT_SHADOW_RADIUS, shadowRadius); if (shadowRadius > 0.0f && !shadowColor.isTransparent()) { paint.setLooper(SkBlurDrawLooper::Create( shadowColor.toSkColor(), SkBlurMaskFilter::ConvertRadiusToSigma(shadowRadius), 0, 0))->unref(); } } return true; }