@Override
    public Pair<Drawable, MarkerInterface> add(final GeoPrimitive item) {

        final int fillColor = GeoStyle.getFillColor(item.getStyle());
        final float rawStrokeWidth = GeoStyle.getStrokeWidth(item.getStyle()) / 1.5f;
        final Style style = Style.builder()
                .strokeWidth(ViewUtils.dpToPixelFloat(rawStrokeWidth))
                .strokeColor(GeoStyle.getStrokeColor(item.getStyle()))
                .fillAlpha(1f) // GeoJsonUtils.colorFromJson() already calculates the color using fill and fill-opacity, don't apply it again
                .fillColor(fillColor)
                .transparent(true) ////See #15029. Following parameter prevents rendering of "darker edges" for overlapping semi-transparent route parts
                .dropDistance(ViewUtils.dpToPixelFloat(1)) //see #15029. This setting stops rendering route parts at some point when zooming out
                .cap(Paint.Cap.BUTT)
                .fixed(true)
                .build();
        final int zLevel = getZLevel(item);

        Drawable drawable = null;
        switch (item.getType()) {
            case MARKER:
                break;
            case CIRCLE:
                drawable = new CircleDrawable(GP_CONVERTER.to(item.getCenter()), item.getRadius(), style);
                break;
            case POLYGON:
                //we have to construct our own GeomBuilder
                //because standard constructorss of PoygonDrawable doesn't support multiple holes
                final GeomBuilder gb = new GeomBuilder();
                addRingToGeoBuilder(gb, item.getPoints());
                if (item.getHoles() != null) {
                    for (List<Geopoint> hole : item.getHoles()) {
                        addRingToGeoBuilder(gb, hole);
                    }
                }
                drawable = new PolygonDrawable(gb.toPolygon(), style);
                break;
            case POLYLINE:
            default:
                drawable = new LineDrawable(GP_CONVERTER.toList(item.getPoints()), style);
                break;
        }

        if (drawable != null) {
            final VectorLayer vectorLayer = getVectorLayer(zLevel, true);
            vectorLayer.add(drawable);
            vectorLayer.update();
        }

        MarkerItem marker = null;
        if (item.getIcon() != null) {
            final PopulateControlledItemizedLayer markerLayer = getMarkerLayer(zLevel, true);
            final GeoIcon icon = item.getIcon();
            marker = new MarkerItem("", "", GP_CONVERTER.to(item.getCenter()));
            marker.setMarker(getMarkerSymbol(icon.getBitmap(), icon.getXAnchor(), icon.getYAnchor(), icon.isFlat()));
            marker.setRotation(item.getIcon().getRotation());
            markerLayer.addItemNoPopulate(marker);
            markerLayersForRefresh.add(zLevel);
        }


        return new Pair<>(drawable, marker);
    }
mimics {@link #removeItem(MarkerInterface)} but w/o calling 'populate'
main/src/main/java/cgeo/geocaching/unifiedmap/geoitemlayer/MapsforgeVtmGeoItemLayer.java