void TransparentRendererCache::CopyTransparentWhiteTo(Canvas &canvas, const WindowProjection &projection) const { if (empty) return; canvas.CopyTransparentWhite(0, 0, projection.GetScreenWidth(), projection.GetScreenHeight(), buffer, 0, 0); }
/** * Draw the final glide groundline (and shading) to the buffer * and copy the transparent buffer to the canvas * @param canvas The drawing canvas * @param rc The area to draw in * @param buffer The drawing buffer */ void MapWindow::DrawTerrainAbove(Canvas &canvas) { // Don't draw at all if // .. no GPS fix // .. not flying // .. feature disabled // .. feature inaccessible if (!Basic().location_available || !Calculated().flight.flying || GetComputerSettings().features.final_glide_terrain == FeaturesSettings::FinalGlideTerrain::OFF || route_planner == nullptr) return; // Create a visitor for the Reach code TriangleCompound visitor(render_projection); // Fill the TriangleCompound with all TriangleFans in range route_planner->AcceptInRange(render_projection.GetScreenBounds(), visitor); // Exit early if not fans found if (visitor.fans.empty()) return; // @todo: update this rendering // Don't draw shade if // .. shade feature disabled // .. pan mode activated if (GetComputerSettings().features.final_glide_terrain == FeaturesSettings::FinalGlideTerrain::SHADE && IsNearSelf()) { #ifdef ENABLE_OPENGL const ScopeVertexPointer vp(&visitor.fans.points[0]); const GLEnable stencil_test(GL_STENCIL_TEST); glClear(GL_STENCIL_BUFFER_BIT); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glStencilFunc(GL_ALWAYS, 1, 1); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); COLOR_WHITE.Set(); visitor.fans.DrawFill(canvas); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glStencilFunc(GL_NOTEQUAL, 1, 1); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); const GLBlend blend(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); canvas.Clear(Color(255, 255, 255, 77)); #elif defined(USE_GDI) // Get a buffer for drawing a mask Canvas &buffer = buffer_canvas; // Set the pattern colors buffer.SetBackgroundOpaque(); buffer.SetBackgroundColor(COLOR_WHITE); buffer.SetTextColor(Color(0xd0, 0xd0, 0xd0)); // Paint the whole buffer canvas with a pattern brush (small dots) buffer.Clear(look.above_terrain_brush); // Select the TerrainLine pen buffer.SelectHollowBrush(); buffer.Select(look.reach_pen_thick); buffer.SetBackgroundColor(Color(0xf0, 0xf0, 0xf0)); // Draw the TerrainLine polygons visitor.fans.DrawOutline(buffer); // Select a white brush (will later be transparent) buffer.SelectNullPen(); buffer.SelectWhiteBrush(); // Draw the TerrainLine polygons to remove the // brush pattern from the polygon areas visitor.fans.DrawFill(buffer); // Copy everything non-white to the buffer canvas.CopyTransparentWhite(0, 0, render_projection.GetScreenWidth(), render_projection.GetScreenHeight(), buffer, 0, 0); /* skip the separate terrain line step below, because we have done it already */ return; #endif } if (visitor.fans.size() == 1) { /* only one fan: we can draw a simple polygon */ #ifdef ENABLE_OPENGL const ScopeVertexPointer vp(&visitor.fans.points[0]); look.reach_pen.Bind(); #else // Select the TerrainLine pen canvas.SelectHollowBrush(); canvas.Select(look.reach_pen); canvas.SetBackgroundOpaque(); canvas.SetBackgroundColor(COLOR_WHITE); // drop out extraneous line from origin #endif // Draw the TerrainLine polygon visitor.fans.DrawOutline(canvas); #ifdef ENABLE_OPENGL look.reach_pen.Unbind(); #endif } else { /* more than one fan (turning reach enabled): we have to use a stencil to draw the outline, because the fans may overlap */ #ifdef ENABLE_OPENGL const ScopeVertexPointer vp(&visitor.fans.points[0]); glEnable(GL_STENCIL_TEST); glClear(GL_STENCIL_BUFFER_BIT); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glStencilFunc(GL_ALWAYS, 1, 1); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); COLOR_WHITE.Set(); visitor.fans.DrawFill(canvas); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glStencilFunc(GL_NOTEQUAL, 1, 1); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); look.reach_pen_thick.Bind(); visitor.fans.DrawOutline(canvas); look.reach_pen_thick.Unbind(); glDisable(GL_STENCIL_TEST); #elif defined(USE_GDI) || defined(USE_MEMORY_CANVAS) // Get a buffer for drawing a mask Canvas &buffer = buffer_canvas; // Paint the whole buffer canvas white ( = transparent) buffer.ClearWhite(); // Select the TerrainLine pen buffer.SelectHollowBrush(); buffer.Select(look.reach_pen_thick); buffer.SetBackgroundOpaque(); buffer.SetBackgroundColor(Color(0xf0, 0xf0, 0xf0)); // Draw the TerrainLine polygons visitor.fans.DrawOutline(buffer); // Select a white brush (will later be transparent) buffer.SelectNullPen(); buffer.SelectWhiteBrush(); // Draw the TerrainLine polygons again to remove // the lines connecting all the polygons // // This removes half of the TerrainLine line width !! visitor.fans.DrawFill(buffer); // Copy everything non-white to the buffer canvas.CopyTransparentWhite(0, 0, render_projection.GetScreenWidth(), render_projection.GetScreenHeight(), buffer, 0, 0); #endif } }