@NonNull
    // method readability will not improve by splitting it up
    @SuppressWarnings("PMD.NPathComplexity")
    private static LayerDrawable createWaypointMarker(final Resources res, final Waypoint waypoint, @Nullable final Geocache cache, final boolean forMap, final boolean applyScaling) {
        final WaypointType waypointType = waypoint.getWaypointType();

        final Drawable marker = new ScalableDrawable(ResourcesCompat.getDrawable(res, waypoint.getMapMarkerId(), null), getWaypointScalingFactor(applyScaling));
        final int size = marker.getIntrinsicWidth();

        final InsetsBuilder insetsBuilder = new InsetsBuilder(res, size, size, true);
        if (forMap) {
            insetsBuilder.withInset(new InsetBuilder(R.drawable.marker_pin, getWaypointScalingFactor(applyScaling)));
        }
        insetsBuilder.withInset(new InsetBuilder(marker));

        if (cache != null && cache.isLinearAlc()) {
            try {
                insetsBuilder.withInset(new InsetBuilder(getStageNumberMarker(res, Integer.parseInt(waypoint.getPrefix()), getWaypointScalingFactor(applyScaling)), Gravity.CENTER));
            } catch (NumberFormatException ignore) {
                insetsBuilder.withInset(new InsetBuilder(new ScalableDrawable(ViewUtils.getDrawable(waypointType.markerId, true), getWaypointScalingFactor(applyScaling)), Gravity.CENTER));
            }
        } else {
            // make drawable mutatable before setting a tint, as otherwise it will change the background for all markers (on Android 7-9)!
            final Drawable waypointTypeIcon = ViewUtils.getDrawable(waypointType.markerId, true);
            if (cache != null && (cache.isDisabled() || cache.isArchived())) {
                DrawableCompat.setTint(waypointTypeIcon, ResourcesCompat.getColor(res, R.color.cacheType_disabled, null));
            }
            insetsBuilder.withInset(new InsetBuilder(new ScalableDrawable(waypointTypeIcon, getWaypointScalingFactor(applyScaling)), Gravity.CENTER));
        }

        if (cache != null && cache.isArchived()) {
            insetsBuilder.withInset(new InsetBuilder(R.drawable.type_overlay_archived, Gravity.CENTER, getWaypointScalingFactor(applyScaling)));
        }
        // bottom-right: visited
        if (waypoint.isVisited()) {
            insetsBuilder.withInset(new InsetBuilder(R.drawable.marker_visited, Gravity.BOTTOM | Gravity.RIGHT, getWaypointScalingFactor(applyScaling)));
        }

        // top-left: emoji
        if (cache != null) {
            final Integer logMarker = getMarkerIdIfLogged(cache);
            if (forMap && logMarker != null) {
                insetsBuilder.withInset(new InsetBuilder(logMarker, Gravity.TOP | Gravity.LEFT));
            } else if (forMap && cache.getAssignedEmoji() != 0) {
                insetsBuilder.withInset(new InsetBuilder(getEmojiMarker(res, cache.getAssignedEmoji(), applyScaling), Gravity.TOP | Gravity.LEFT));
            } else if (forMap) {
                insetsBuilder.withInset(new InsetBuilder(getTypeMarker(res, cache, true, applyScaling, false), Gravity.TOP | Gravity.LEFT));
            }
            addListMarkers(res, insetsBuilder, getAssignedMarkers(cache), false, applyScaling);
        }
        final LayerDrawable ld = buildLayerDrawable(insetsBuilder, 8, 8);
        if ((waypoint.isVisited() || (cache != null && cache.isFound())) && Settings.getVisitedWaypointsSemiTransparent()) {
            ld.setAlpha(144);
        }
        return ld;
    }
Build the drawable for a given waypoint.

@param res      the resources to use
@param waypoint the waypoint to build the drawable for
@return a drawable representing the current waypoint status
main/src/main/java/cgeo/geocaching/utils/MapMarkerUtils.java