void GaugeVario::RenderZero(Canvas &canvas) { if (look.inverse) canvas.SelectWhitePen(); else canvas.SelectBlackPen(); canvas.DrawLine(0, yoffset, Layout::Scale(17), yoffset); canvas.DrawLine(0, yoffset + 1, Layout::Scale(17), yoffset + 1); }
void GlueMapWindow::DrawCrossHairs(Canvas &canvas) const { Pen dash_pen(Pen::DASH, 1, COLOR_DARK_GRAY); canvas.Select(dash_pen); const RasterPoint center = render_projection.GetScreenOrigin(); canvas.DrawLine(center.x + 20, center.y, center.x - 20, center.y); canvas.DrawLine(center.x, center.y + 20, center.x, center.y - 20); }
static void DrawArrow(Canvas &canvas, RasterPoint point, const fixed mag, const Angle angle) { const FastRotation r(angle); auto p = r.Rotate(mag, fixed(0)); canvas.DrawLine(point, point + RasterPoint((int)p.x, (int)p.y)); p = r.Rotate(mag - fixed(5), fixed(-3)); canvas.DrawLine(point, point + RasterPoint((int)p.x, (int)p.y)); p = r.Rotate(mag - fixed(5), fixed(3)); canvas.DrawLine(point, point + RasterPoint((int)p.x, (int)p.y)); }
void GlueMapWindow::DrawCrossHairs(Canvas &canvas) const { if (!render_projection.IsValid()) return; canvas.Select(look.overlay.crosshair_pen); const auto center = render_projection.GetScreenOrigin(); canvas.DrawLine(center.x + 20, center.y, center.x - 20, center.y); canvas.DrawLine(center.x, center.y + 20, center.x, center.y - 20); }
void TitleBar::MinimizeButton::OnDraw(const Context &context) { Canvas *canvas = context.canvas(); int scale = context.surface()->GetScale(); const RectF &rect = GetBounds(); canvas->Scale(scale, scale); Paint paint; paint.SetAntiAlias(true); if (IsHovered()) { if (IsPressed()) { paint.SetColor(Theme::GetData().title_bar.highlight.foreground.colors[0]); paint.SetStyle(Paint::Style::kStyleFill); canvas->DrawCircle(rect.center_x(), rect.center_y(), 7.f, paint); paint.Reset(); paint.SetAntiAlias(true); } paint.SetStyle(Paint::Style::kStyleStroke); paint.SetColor(Theme::GetData().title_bar.active.foreground.colors[0]); paint.SetStrokeWidth(1.f); canvas->DrawCircle(rect.center_x(), rect.center_y(), 6.5f, paint); } paint.SetColor(Theme::GetData().title_bar.active.foreground.colors[0]); paint.SetStrokeWidth(1.5f); canvas->DrawLine(rect.center_x() - 4.f, rect.center_y(), rect.center_x() + 4.f, rect.center_y(), paint); }
result CameraOverlayPanel::OnDraw(void) { Canvas * pCanvas = GetCanvasN(); pCanvas->Clear(); if (bgbmp != null) { pCanvas->DrawBitmap(bgbmpsizedest, *bgbmp, bgbmpsizesrc); } pCanvas->FillRectangle(Color(0,0,0,100), Rectangle(0, 420, 800, 60)); if (ftype == LEFTCAP) { drawingclass_->FDrawTextToCanvas(pCanvas, Rectangle(0,420,800,60), L"Left eye capture", 28, Osp::Graphics::FONT_STYLE_BOLD, false, Color::COLOR_RED, Osp::Graphics::TEXT_ALIGNMENT_CENTER, Osp::Graphics::TEXT_ALIGNMENT_MIDDLE); pCanvas->SetForegroundColor(Color::COLOR_RED); } else if (ftype == RIGHTCAP) { drawingclass_->FDrawTextToCanvas(pCanvas, Rectangle(0,420,800,60), L"Right eye capture", 28, Osp::Graphics::FONT_STYLE_BOLD, false, Color::COLOR_BLUE, Osp::Graphics::TEXT_ALIGNMENT_CENTER, Osp::Graphics::TEXT_ALIGNMENT_MIDDLE); pCanvas->SetForegroundColor(Color::COLOR_BLUE); } else if (ftype == ALIGN) { drawingclass_->FDrawTextToCanvas(pCanvas, Rectangle(0,420,800,60), L"Alignment", 28, Osp::Graphics::FONT_STYLE_BOLD, false, Color::COLOR_GREEN, Osp::Graphics::TEXT_ALIGNMENT_CENTER, Osp::Graphics::TEXT_ALIGNMENT_MIDDLE); pCanvas->SetForegroundColor(Color::COLOR_GREEN); } else if (ftype == PAUSE) { drawingclass_->FDrawTextToCanvas(pCanvas, Rectangle(0,420,800,60), L"Paused [resume in 2 sec]", 28, Osp::Graphics::FONT_STYLE_BOLD, false, Color::COLOR_GREEN, Osp::Graphics::TEXT_ALIGNMENT_CENTER, Osp::Graphics::TEXT_ALIGNMENT_MIDDLE); pCanvas->SetForegroundColor(Color::COLOR_RED); } if ((ftype == LEFTCAP) || (ftype == RIGHTCAP)) { pCanvas->SetLineWidth(2); /*int boxw = 200; int boxh = 120;*/ int boxw2 = 100; int boxh2 = 60; int gapw = 50; int gaph = 30; //top left corner pCanvas->DrawLine(Point(400-boxw2,240-boxh2), Point(400-boxw2+gapw, 240-boxh2)); pCanvas->DrawLine(Point(400-boxw2,240-boxh2), Point(400-boxw2, 240-boxh2+gaph)); //top right corner pCanvas->DrawLine(Point(400+boxw2-gapw,240-boxh2), Point(400+boxw2, 240-boxh2)); pCanvas->DrawLine(Point(400+boxw2,240-boxh2), Point(400+boxw2, 240-boxh2+gaph)); //bottom left corner pCanvas->DrawLine(Point(400-boxw2,240+boxh2), Point(400-boxw2+gapw, 240+boxh2)); pCanvas->DrawLine(Point(400-boxw2,240+boxh2), Point(400-boxw2, 240+boxh2-gaph)); //bottom right corner pCanvas->DrawLine(Point(400+boxw2-gapw,240+boxh2), Point(400+boxw2, 240+boxh2)); pCanvas->DrawLine(Point(400+boxw2,240+boxh2), Point(400+boxw2, 240+boxh2-gaph)); } delete pCanvas; return E_SUCCESS; }
void ThermalAssistantWindow::PaintRadarPlane(Canvas &canvas) const { canvas.Select(look.plane_pen); PixelScalar x = mid.x + (LeftTurn() ? radius : -radius); canvas.DrawLine(x + Layout::FastScale(small ? 5 : 10), mid.y - Layout::FastScale(small ? 1 : 2), x - Layout::FastScale(small ? 5 : 10), mid.y - Layout::FastScale(small ? 1 : 2)); canvas.DrawLine(x, mid.y - Layout::FastScale(small ? 3 : 6), x, mid.y + Layout::FastScale(small ? 3 : 6)); canvas.DrawLine(x + Layout::FastScale(small ? 2 : 4), mid.y + Layout::FastScale(small ? 2 : 4), x - Layout::FastScale(small ? 2 : 4), mid.y + Layout::FastScale(small ? 2 : 4)); }
void GlueMapWindow::DrawStallRatio(Canvas &canvas, const PixelRect &rc) const { if (Basic().stall_ratio_available) { // JMW experimental, display stall sensor fixed s = Clamp(Basic().stall_ratio, fixed(0), fixed(1)); PixelScalar m((rc.bottom - rc.top) * s * s); canvas.SelectBlackPen(); canvas.DrawLine(rc.right - 1, rc.bottom - m, rc.right - 11, rc.bottom - m); } }
void GlueMapWindow::DrawStallRatio(Canvas &canvas, const PixelRect &rc) const { if (Basic().stall_ratio_available) { // JMW experimental, display stall sensor auto s = Clamp(Basic().stall_ratio, 0., 1.); int m = rc.GetHeight() * s * s; canvas.SelectBlackPen(); canvas.DrawLine(rc.right - 1, rc.bottom - m, rc.right - 11, rc.bottom - m); } }
/** * Paint a plane symbol in the middle of the radar on the given canvas * @param canvas The canvas to paint on */ void FlarmTrafficWindow::PaintRadarPlane(Canvas &canvas) const { canvas.Select(look.plane_pen); IntPoint2D p1(Layout::FastScale(small ? 5 : 10), -Layout::FastScale(small ? 1 : 2)); IntPoint2D p2(-p1.x, p1.y); if (enable_north_up) { p1 = fir.Rotate(p1); p2 = fir.Rotate(p2); } canvas.DrawLine(radar_mid.x + p1.x, radar_mid.y + p1.y, radar_mid.x + p2.x, radar_mid.y + p2.y); p2 = { 0, Layout::FastScale(small ? 3 : 6) }; p1 = { 0, -p2.y }; if (enable_north_up) { p1 = fir.Rotate(p1); p2 = fir.Rotate(p2); } canvas.DrawLine(radar_mid.x + p1.x, radar_mid.y + p1.y, radar_mid.x + p2.x, radar_mid.y + p2.y); p1.x = Layout::FastScale(small ? 2 : 4); p1.y = p1.x; p2 = { -p1.x, p1.y }; if (enable_north_up) { p1 = fir.Rotate(p1); p2 = fir.Rotate(p2); } canvas.DrawLine(radar_mid.x + p1.x, radar_mid.y + p1.y, radar_mid.x + p2.x, radar_mid.y + p2.y); }
void TrackLineRenderer::Draw(Canvas &canvas, const Angle screen_angle, const Angle track_angle, const RasterPoint pos) { const auto sc = (track_angle - screen_angle).SinCos(); const auto x = sc.first, y = sc.second; RasterPoint end; end.x = pos.x + iround(x * 400); end.y = pos.y - iround(y * 400); canvas.Select(look.track_line_pen); canvas.DrawLine(pos, end); }
void MapItemListWidget::OnPaintItem(Canvas &canvas, const PixelRect rc, unsigned idx) { const MapItem &item = *list[idx]; renderer.Draw(canvas, rc, item, &CommonInterface::Basic().flarm.traffic); if ((settings.item_list.add_arrival_altitude && item.type == MapItem::Type::ARRIVAL_ALTITUDE) || (!settings.item_list.add_arrival_altitude && item.type == MapItem::Type::LOCATION)) { canvas.SelectBlackPen(); canvas.DrawLine(rc.left, rc.bottom - 1, rc.right, rc.bottom - 1); } }
void MapItemListWidget::OnPaintItem(Canvas &canvas, const PixelRect rc, unsigned idx) { const MapItem &item = *list[idx]; MapItemListRenderer::Draw(canvas, rc, item, dialog_look, look, traffic_look, final_glide_look, settings); if ((settings.item_list.add_arrival_altitude && item.type == MapItem::Type::ARRIVAL_ALTITUDE) || (!settings.item_list.add_arrival_altitude && item.type == MapItem::Type::LOCATION)) { canvas.SelectBlackPen(); canvas.DrawLine(rc.left, rc.bottom - 1, rc.right, rc.bottom - 1); } }
void OZWindow::OnPaint(Canvas &canvas) { canvas.ClearWhite(); if (oz == NULL) return; const int offset = 0; roz.Draw(canvas, OZRenderer::LAYER_SHADE, projection, *oz, offset); roz.Draw(canvas, OZRenderer::LAYER_INACTIVE, projection, *oz, offset); roz.Draw(canvas, OZRenderer::LAYER_ACTIVE, projection, *oz, offset); /* debugging for ObservationZone::GetBoundary() */ Pen pen(1, COLOR_RED); canvas.Select(pen); const OZBoundary boundary = oz->GetBoundary(); for (auto i = boundary.begin(), end = boundary.end(); i != end; ++i) { RasterPoint p = projection.GeoToScreen(*i); canvas.DrawLine(p.x - 3, p.y - 3, p.x + 3, p.y + 3); canvas.DrawLine(p.x + 3, p.y - 3, p.x - 3, p.y + 3); } }
void WindArrowRenderer::DrawArrow(Canvas &canvas, PixelPoint pos, Angle angle, unsigned length, WindArrowStyle arrow_style, int offset) { // Draw arrow BulkPixelPoint arrow[] = { { 0, -offset + 3 }, { -6, -offset - 3 - int(length) }, { 0, -offset + 3 - int(length) }, { 6, -offset - 3 - int(length) }, }; // Rotate the arrow PolygonRotateShift(arrow, ARRAY_SIZE(arrow), pos, angle); canvas.Select(look.arrow_pen); canvas.Select(look.arrow_brush); canvas.DrawPolygon(arrow, ARRAY_SIZE(arrow)); // Draw arrow tail if (arrow_style == WindArrowStyle::FULL_ARROW) { BulkPixelPoint tail[] = { { 0, -offset + 3 }, { 0, -offset - 3 - int(std::min(20u, length) * 3u) }, }; PolygonRotateShift(tail, ARRAY_SIZE(tail), pos, angle); canvas.Select(look.tail_pen); canvas.DrawLine(tail[0], tail[1]); } }
void WindArrowRenderer::DrawArrow(Canvas &canvas, RasterPoint pos, Angle angle, PixelScalar length, WindArrowStyle arrow_style, PixelScalar offset) { // Draw arrow RasterPoint arrow[] = { { 0, (PixelScalar)(-offset + 3) }, { -6, (PixelScalar)(-offset - 3 - length) }, { 0, (PixelScalar)(-offset + 3 - length) }, { 6, (PixelScalar)(-offset - 3 - length) }, }; // Rotate the arrow PolygonRotateShift(arrow, ARRAY_SIZE(arrow), pos.x, pos.y, angle); canvas.Select(look.arrow_pen); canvas.Select(look.arrow_brush); canvas.DrawPolygon(arrow, ARRAY_SIZE(arrow)); // Draw arrow tail if (arrow_style == WindArrowStyle::FULL_ARROW) { RasterPoint tail[] = { { 0, (PixelScalar)(-offset + 3) }, { 0, -offset - 3 - std::min(PixelScalar(20), length) * 3 }, }; PolygonRotateShift(tail, ARRAY_SIZE(tail), pos.x, pos.y, angle); canvas.Select(look.tail_pen); canvas.DrawLine(tail[0], tail[1]); } }
void FinalGlideBarRenderer::Draw(Canvas &canvas, const PixelRect &rc, const DerivedInfo &calculated, const GlideSettings &glide_settings, const bool final_glide_bar_mc0_enabled) const { #ifdef ENABLE_OPENGL const GLEnable blend(GL_BLEND); #endif RasterPoint GlideBar[6] = { { 0, 0 }, { 9, -9 }, { 18, 0 }, { 18, 0 }, { 9, 0 }, { 0, 0 } }; RasterPoint GlideBar0[4] = { { 0, 0 }, { 9, -9 }, { 9, 0 }, { 0, 0 } }; RasterPoint clipping_arrow[6] = { { 0, 0 }, { 9, 9 }, { 18, 0 }, { 18, 6 }, { 9, 15 }, { 0, 6 } }; RasterPoint clipping_arrow0[4] = { { 0, 0 }, { 9, 9 }, { 9, 15 }, { 0, 6 } }; TCHAR Value[10]; const TaskStats &task_stats = calculated.task_stats; const ElementStat &total = task_stats.total; const GlideResult &solution = total.solution_remaining; const GlideResult &solution_mc0 = total.solution_mc0; if (!task_stats.task_valid || !solution.IsOk() || !solution_mc0.IsDefined()) return; const int y0 = (rc.bottom + rc.top) / 2; PixelScalar dy_glidebar = 0; PixelScalar dy_glidebar0 = 0; FormatUserAltitude(solution.SelectAltitudeDifference(glide_settings), Value, false); canvas.Select(*look.font); const PixelSize text_size = canvas.CalcTextSize(Value); PixelScalar clipping_arrow_offset = Layout::Scale(4); PixelScalar clipping_arrow0_offset = Layout::Scale(4); // 468 meters is it's size. Will be divided by 9 to fit screen resolution. int altitude_difference = (int) solution.SelectAltitudeDifference(glide_settings); int altitude_difference0 = (int) solution_mc0.SelectAltitudeDifference(glide_settings); // TODO feature: should be an angle if in final glide mode // cut altitude_difference at +- 468 meters (55 units) if (altitude_difference > 468) altitude_difference = 468; if (altitude_difference < -468) altitude_difference = -468; // 55 units is size, 468 meters div by 9 means 55. int Offset = altitude_difference / 9; Offset = Layout::Scale(Offset); if (altitude_difference <= 0) { GlideBar[1].y = Layout::Scale(9); dy_glidebar = text_size.cy + 2; } else { GlideBar[1].y = -Layout::Scale(9); clipping_arrow[1].y = -clipping_arrow[1].y; clipping_arrow[3].y = -clipping_arrow[3].y; clipping_arrow[4].y = -clipping_arrow[4].y; clipping_arrow[5].y = -clipping_arrow[5].y; clipping_arrow_offset = -clipping_arrow_offset; dy_glidebar = -1; } // cut altitude_difference0 at +- 468 meters (55 units) if (altitude_difference0 > 468) altitude_difference0 = 468; if (altitude_difference0 < -468) altitude_difference0 = -468; // 55 units is size, therefore div by 9. int Offset0 = altitude_difference0 / 9; Offset0 = Layout::Scale(Offset0); if (altitude_difference0 <= 0) { GlideBar0[1].y = Layout::Scale(9); dy_glidebar0 = text_size.cy + 2; } else { GlideBar0[1].y = -Layout::Scale(9); clipping_arrow0[1].y = -clipping_arrow0[1].y; clipping_arrow0[2].y = -clipping_arrow0[2].y; clipping_arrow0[3].y = -clipping_arrow0[3].y; clipping_arrow0_offset = -clipping_arrow0_offset; dy_glidebar0 = -1; } for (unsigned i = 0; i < 6; i++) { GlideBar[i].y += y0 + dy_glidebar; GlideBar[i].x = Layout::Scale(GlideBar[i].x) + rc.left; } GlideBar[0].y -= Offset; GlideBar[1].y -= Offset; GlideBar[2].y -= Offset; for (unsigned i = 0; i < 4; i++) { GlideBar0[i].y += y0 + dy_glidebar0; GlideBar0[i].x = Layout::Scale(GlideBar0[i].x) + rc.left; } GlideBar0[0].y -= Offset0; GlideBar0[1].y -= Offset0; if ((altitude_difference0 >= altitude_difference) && (altitude_difference > 0)) { // both above and mc0 arrow larger than mc arrow GlideBar0[2].y = GlideBar[1].y; // both below GlideBar0[3].y = GlideBar[0].y; } // prepare clipping arrow for (unsigned i = 0; i < 6; i++) { clipping_arrow[i].y = Layout::Scale(clipping_arrow[i].y) + y0 - Offset + clipping_arrow_offset + dy_glidebar; clipping_arrow[i].x = Layout::Scale(clipping_arrow[i].x) + rc.left; } // prepare clipping arrow mc0 for (unsigned i = 0; i < 4; i++) { clipping_arrow0[i].y = Layout::Scale(clipping_arrow0[i].y) + y0 - Offset0 + clipping_arrow0_offset + dy_glidebar0; clipping_arrow0[i].x = Layout::Scale(clipping_arrow0[i].x) + rc.left; } // draw actual glide bar if (altitude_difference <= 0) { if (calculated.common_stats.landable_reachable) { canvas.Select(look.pen_below_landable); canvas.Select(look.brush_below_landable); } else { canvas.Select(look.pen_below); canvas.Select(look.brush_below); } } else { canvas.Select(look.pen_above); canvas.Select(look.brush_above); } canvas.DrawPolygon(GlideBar, 6); // draw clipping arrow if ((altitude_difference <= -468 ) || (altitude_difference >= 468)) canvas.DrawPolygon(clipping_arrow, 6); // draw glide bar at mc 0 if (altitude_difference0 <= 0 && final_glide_bar_mc0_enabled) { if (calculated.common_stats.landable_reachable) { canvas.Select(look.pen_below_landable); canvas.Select(look.brush_below_landable_mc0); } else { canvas.Select(look.pen_below); canvas.Select(look.brush_below_mc0); } } else { canvas.Select(look.pen_above); canvas.Select(look.brush_above_mc0); } if ( ( (altitude_difference != altitude_difference0) || (altitude_difference0 < 0) ) && final_glide_bar_mc0_enabled) { canvas.DrawPolygon(GlideBar0, 4); if ((altitude_difference0 <= -468 ) || (altitude_difference0 >= 468)) canvas.DrawPolygon(clipping_arrow0, 4); } // draw cross (x) on final glide bar if unreachable at current Mc // or above final glide but impeded by obstacle int cross_sign = 0; if (!total.IsAchievable()) cross_sign = 1; if (calculated.terrain_warning && (altitude_difference>0)) cross_sign = -1; if (cross_sign != 0) { canvas.Select(task_look.bearing_pen); canvas.DrawLine(Layout::Scale(9 - 5), y0 + cross_sign * Layout::Scale(9 - 5), Layout::Scale(9 + 5), y0 + cross_sign * Layout::Scale(9 + 5)); canvas.DrawLine(Layout::Scale(9 - 5), y0 + cross_sign * Layout::Scale(9 + 5), Layout::Scale(9 + 5), y0 + cross_sign * Layout::Scale(9 - 5)); } canvas.SetTextColor(COLOR_BLACK); canvas.SetBackgroundColor(COLOR_WHITE); TextInBoxMode style; style.shape = LabelShape::ROUNDED_BLACK; style.move_in_view = true; if (text_size.cx < Layout::Scale(18)) { style.align = TextInBoxMode::Alignment::RIGHT; TextInBox(canvas, Value, Layout::Scale(18), y0, style, rc); } else TextInBox(canvas, Value, 0, y0, style, rc); }
void HorizonRenderer::Draw(Canvas &canvas, const PixelRect &rc, const HorizonLook &look, const AttitudeState &attitude) { /* This feature of having a backup artificial horizon based on inferred orientation from GPS and vario data is useful, and reasonably well tested, but has the issue of potentially invalidating use of XCSoar in FAI contests due to rule ref Annex A to Section 3 (2010 Edition) 4.1.2 "No instruments permitting pilots to fly without visual reference to the ground may be carried on board, even if made unserviceable." The quality of XCSoar's pseudo-AH is arguably good enough that this violates the rule. We need to seek clarification as to whether this is the case or not. */ RasterPoint center; center.y = (rc.top + rc.bottom) / 2; center.x = (rc.left + rc.right) / 2; const int radius = min(rc.right - rc.left, rc.bottom - rc.top) / 2 - Layout::Scale(1); #define fixed_div fixed(1.0 / 50.0) #define fixed_89 fixed_int_constant(89) fixed bank_degrees = attitude.bank_angle_available ? attitude.bank_angle.Degrees() : fixed_zero; fixed pitch_degrees = attitude.pitch_angle_available ? attitude.pitch_angle.Degrees() : fixed_zero; fixed phi = max(-fixed_89, min(fixed_89, bank_degrees)); fixed alpha = fixed_rad_to_deg * acos(max(-fixed_one,min(fixed_one, pitch_degrees * fixed_div))); fixed sphi = fixed_180 - phi; Angle alpha1 = Angle::Degrees(sphi - alpha); Angle alpha2 = Angle::Degrees(sphi + alpha); // draw sky part canvas.Select(look.sky_pen); canvas.Select(look.sky_brush); canvas.DrawSegment(center.x, center.y, radius, alpha2, alpha1, true); // draw ground part canvas.Select(look.terrain_pen); canvas.Select(look.terrain_brush); canvas.DrawSegment(center.x, center.y, radius, alpha1, alpha2, true); // draw aircraft symbol canvas.Select(look.aircraft_pen); canvas.DrawLine(center.x + radius / 2, center.y, center.x - radius / 2, center.y); canvas.DrawLine(center.x, center.y - radius / 4, center.x, center.y); // draw 45 degree dash marks const UPixelScalar rr2p = uround(radius * fixed_sqrt_half) + Layout::Scale(1); const UPixelScalar rr2n = rr2p - Layout::Scale(2); canvas.DrawLine(center.x + rr2p, center.y - rr2p, center.x + rr2n, center.y - rr2n); canvas.DrawLine(center.x - rr2p, center.y - rr2p, center.x - rr2n, center.y - rr2n); }
void ThermalAssistantWindow::PaintAdvisor(Canvas &canvas, const LiftPoints &lift_points) const { canvas.DrawLine(mid, lift_points.GetAverage()); }
void TrailRenderer::Draw(Canvas &canvas, const TraceComputer &trace_computer, const WindowProjection &projection, unsigned min_time, bool enable_traildrift, const RasterPoint pos, const NMEAInfo &basic, const DerivedInfo &calculated, const TrailSettings &settings) { if (settings.length == TrailSettings::Length::OFF) return; if (!LoadTrace(trace_computer, min_time, projection)) return; if (!calculated.wind_available) enable_traildrift = false; GeoPoint traildrift; if (enable_traildrift) { GeoPoint tp1 = FindLatitudeLongitude(basic.location, calculated.wind.bearing, calculated.wind.norm); traildrift = basic.location - tp1; } auto minmax = GetMinMax(settings.type, trace); auto value_min = minmax.first; auto value_max = minmax.second; bool scaled_trail = settings.scaling_enabled && projection.GetMapScale() <= 6000; const GeoBounds bounds = projection.GetScreenBounds().Scale(4); RasterPoint last_point = RasterPoint(0, 0); bool last_valid = false; for (auto it = trace.begin(), end = trace.end(); it != end; ++it) { const GeoPoint gp = enable_traildrift ? it->GetLocation().Parametric(traildrift, it->CalculateDrift(basic.time)) : it->GetLocation(); if (!bounds.IsInside(gp)) { /* the point is outside of the MapWindow; don't paint it */ last_valid = false; continue; } RasterPoint pt = projection.GeoToScreen(gp); if (last_valid) { if (settings.type == TrailSettings::Type::ALTITUDE) { unsigned index = GetAltitudeColorIndex(it->GetAltitude(), value_min, value_max); canvas.Select(look.trail_pens[index]); canvas.DrawLinePiece(last_point, pt); } else { unsigned color_index = GetSnailColorIndex(it->GetVario(), value_min, value_max); if (it->GetVario() < 0 && (settings.type == TrailSettings::Type::VARIO_1_DOTS || settings.type == TrailSettings::Type::VARIO_2_DOTS || settings.type == TrailSettings::Type::VARIO_DOTS_AND_LINES)) { canvas.SelectNullPen(); canvas.Select(look.trail_brushes[color_index]); canvas.DrawCircle((pt.x + last_point.x) / 2, (pt.y + last_point.y) / 2, look.trail_widths[color_index]); } else { // positive vario case if (settings.type == TrailSettings::Type::VARIO_DOTS_AND_LINES) { canvas.Select(look.trail_brushes[color_index]); canvas.Select(look.trail_pens[color_index]); //fixed-width pen canvas.DrawCircle((pt.x + last_point.x) / 2, (pt.y + last_point.y) / 2, look.trail_widths[color_index]); } else if (scaled_trail) // width scaled to vario canvas.Select(look.scaled_trail_pens[color_index]); else // fixed-width pen canvas.Select(look.trail_pens[color_index]); canvas.DrawLinePiece(last_point, pt); } } } last_point = pt; last_valid = true; } if (last_valid) canvas.DrawLine(last_point, pos); }
void ScrollBar::Paint(Canvas &canvas) const { // Prepare Pen canvas.SelectBlackPen(); // ################### // #### ScrollBar #### // ################### // draw rectangle around entire scrollbar area canvas.DrawTwoLines(rc.left, rc.top, rc.left, rc.bottom, rc.right, rc.bottom); canvas.DrawTwoLines(rc.right, rc.bottom, rc.right, rc.top, rc.left, rc.top); // ################### // #### Buttons #### // ################### UPixelScalar arrow_padding = max(UPixelScalar(GetWidth() / 4), UPixelScalar(4)); canvas.SelectBlackBrush(); PixelRect up_arrow_rect = rc; ++up_arrow_rect.left; up_arrow_rect.bottom = up_arrow_rect.top + GetWidth(); canvas.DrawLine(up_arrow_rect.left, up_arrow_rect.bottom, up_arrow_rect.right, up_arrow_rect.bottom); canvas.DrawButton(up_arrow_rect, false); RasterPoint up_arrow[3] = { { PixelScalar((up_arrow_rect.left + rc.right) / 2), PixelScalar(up_arrow_rect.top + arrow_padding) }, { PixelScalar(up_arrow_rect.left + arrow_padding), PixelScalar(up_arrow_rect.bottom - arrow_padding) }, { PixelScalar(rc.right - arrow_padding), PixelScalar(up_arrow_rect.bottom - arrow_padding) }, }; canvas.DrawTriangleFan(up_arrow, ARRAY_SIZE(up_arrow)); PixelRect down_arrow_rect = rc; ++down_arrow_rect.left; down_arrow_rect.top = down_arrow_rect.bottom - GetWidth(); canvas.DrawLine(down_arrow_rect.left, down_arrow_rect.top - 1, down_arrow_rect.right, down_arrow_rect.top - 1); canvas.DrawButton(down_arrow_rect, false); RasterPoint down_arrow[3] = { { PixelScalar((down_arrow_rect.left + rc.right) / 2), PixelScalar(down_arrow_rect.bottom - arrow_padding) }, { PixelScalar(down_arrow_rect.left + arrow_padding), PixelScalar(down_arrow_rect.top + arrow_padding) }, { PixelScalar(rc.right - arrow_padding), PixelScalar(down_arrow_rect.top + arrow_padding) }, }; canvas.DrawTriangleFan(down_arrow, ARRAY_SIZE(down_arrow)); // ################### // #### Slider #### // ################### if (rc_slider.top + 4 < rc_slider.bottom) { canvas.DrawLine(rc_slider.left, rc_slider.top, rc_slider.right, rc_slider.top); canvas.DrawLine(rc_slider.left, rc_slider.bottom, rc_slider.right, rc_slider.bottom); PixelRect rc_slider2 = rc_slider; ++rc_slider2.left; ++rc_slider2.top; canvas.DrawButton(rc_slider2, false); } // fill the rest with darker gray if (up_arrow_rect.bottom + 1 < rc_slider.top) canvas.DrawFilledRectangle(rc.left + 1, up_arrow_rect.bottom + 1, rc.right, rc_slider.top, COLOR_GRAY); if (rc_slider.bottom < down_arrow_rect.top) canvas.DrawFilledRectangle(rc.left + 1, rc_slider.bottom, rc.right, down_arrow_rect.top, COLOR_GRAY); }
void AirspaceLabelRenderer::DrawInternal(Canvas &canvas, #ifndef ENABLE_OPENGL Canvas &stencil_canvas, #endif const WindowProjection &projection, const AirspaceRendererSettings &settings, const AirspaceWarningCopy &awc, const AirspacePredicate &visible, const AirspaceWarningConfig &config) { AirspaceLabelList labels; for (const auto &i : airspaces->QueryWithinRange(projection.GetGeoScreenCenter(), projection.GetScreenDistanceMeters())) { const AbstractAirspace &airspace = i.GetAirspace(); if (visible(airspace)) labels.Add(airspace.GetCenter(), airspace.GetType(), airspace.GetBase(), airspace.GetTop()); } if(settings.label_selection == AirspaceRendererSettings::LabelSelection::ALL) { labels.Sort(config); // default paint settings canvas.SetTextColor(look.label_text_color); canvas.Select(*look.name_font); canvas.Select(look.label_pen); canvas.Select(look.label_brush); canvas.SetBackgroundTransparent(); // draw TCHAR topText[NAME_SIZE + 1]; TCHAR baseText[NAME_SIZE + 1]; for (const auto &label : labels) { // size of text AirspaceFormatter::FormatAltitudeShort(topText, label.top, false); PixelSize topSize = canvas.CalcTextSize(topText); AirspaceFormatter::FormatAltitudeShort(baseText, label.base, false); PixelSize baseSize = canvas.CalcTextSize(baseText); int labelWidth = std::max(topSize.cx, baseSize.cx) + 2 * Layout::GetTextPadding(); int labelHeight = topSize.cy + baseSize.cy; // box const auto pos = projection.GeoToScreen(label.pos); PixelRect rect; rect.left = pos.x - labelWidth / 2; rect.top = pos.y; rect.right = rect.left + labelWidth; rect.bottom = rect.top + labelHeight; canvas.Rectangle(rect.left, rect.top, rect.right, rect.bottom); #ifdef USE_GDI canvas.DrawLine(rect.left + Layout::GetTextPadding(), rect.top + labelHeight / 2, rect.right - Layout::GetTextPadding(), rect.top + labelHeight / 2); #else canvas.DrawHLine(rect.left + Layout::GetTextPadding(), rect.right - Layout::GetTextPadding(), rect.top + labelHeight / 2, look.label_pen.GetColor()); #endif // top text int x = rect.right - Layout::GetTextPadding() - topSize.cx; int y = rect.top; canvas.DrawText(x, y, topText); // base text x = rect.right - Layout::GetTextPadding() - baseSize.cx; y = rect.bottom - baseSize.cy; canvas.DrawText(x, y, baseText); } } }
void FinalGlideBarRenderer::Draw(Canvas &canvas, const PixelRect &rc, const DerivedInfo &calculated, const GlideSettings &glide_settings, const bool final_glide_bar_mc0_enabled) const { #ifdef ENABLE_OPENGL const ScopeAlphaBlend alpha_blend; #endif BulkPixelPoint GlideBar[6] = { { 0, 0 }, { 9, -9 }, { 18, 0 }, { 18, 0 }, { 9, 0 }, { 0, 0 } }; BulkPixelPoint GlideBar0[4] = { { 0, 0 }, { 9, -9 }, { 9, 0 }, { 0, 0 } }; BulkPixelPoint clipping_arrow[6] = { { 0, 0 }, { 9, 9 }, { 18, 0 }, { 18, 6 }, { 9, 15 }, { 0, 6 } }; BulkPixelPoint clipping_arrow0[4] = { { 0, 0 }, { 9, 9 }, { 9, 15 }, { 0, 6 } }; TCHAR Value[10]; const TaskStats &task_stats = calculated.task_stats; const ElementStat &total = task_stats.total; const GlideResult &solution = total.solution_remaining; const GlideResult &solution_mc0 = total.solution_mc0; if (!task_stats.task_valid || !solution.IsOk() || !solution_mc0.IsDefined()) return; const int y0 = (rc.bottom + rc.top) / 2; /* NOTE: size_divisor replaces the fixed value 9 that was used throughout * the code below which caused fixed size rendering regardless of * map size (except the effects of Layout::Scale()). This method * is not usable with variable map sizes (e.g. because of the cross-section * area). size_divisor is used to introduce a screen size dependent scaling. * That workaround is an ugly hack and needs a rework. */ const int size_divisor = std::max(Layout::Scale(3000u / rc.GetHeight()), 4u); int dy_glidebar = 0; int dy_glidebar0 = 0; FormatUserAltitude(solution.SelectAltitudeDifference(glide_settings), Value, false); canvas.Select(*look.font); const PixelSize text_size = canvas.CalcTextSize(Value); int clipping_arrow_offset = Layout::Scale(4); int clipping_arrow0_offset = Layout::Scale(4); // 468 meters is it's size. Will be divided by 9 to fit screen resolution. int altitude_difference = (int) solution.SelectAltitudeDifference(glide_settings); int altitude_difference0 = (int) solution_mc0.SelectAltitudeDifference(glide_settings); // TODO feature: should be an angle if in final glide mode // cut altitude_difference at +- 468 meters (55 units) if (altitude_difference > 468) altitude_difference = 468; if (altitude_difference < -468) altitude_difference = -468; // 55 units is size, 468 meters div by 9 means 55. int Offset = altitude_difference / size_divisor; Offset = Layout::Scale(Offset); if (altitude_difference <= 0) { GlideBar[1].y = Layout::Scale(9); dy_glidebar = text_size.cy + 2; } else { GlideBar[1].y = -Layout::Scale(9); clipping_arrow[1].y = -clipping_arrow[1].y; clipping_arrow[3].y = -clipping_arrow[3].y; clipping_arrow[4].y = -clipping_arrow[4].y; clipping_arrow[5].y = -clipping_arrow[5].y; clipping_arrow_offset = -clipping_arrow_offset; dy_glidebar = -1; } // cut altitude_difference0 at +- 468 meters (55 units) if (altitude_difference0 > 468) altitude_difference0 = 468; if (altitude_difference0 < -468) altitude_difference0 = -468; // 55 units is size, therefore div by 9. int Offset0 = altitude_difference0 / size_divisor; Offset0 = Layout::Scale(Offset0); if (altitude_difference0 <= 0) { GlideBar0[1].y = Layout::Scale(9); dy_glidebar0 = text_size.cy + 2; } else { GlideBar0[1].y = -Layout::Scale(9); clipping_arrow0[1].y = -clipping_arrow0[1].y; clipping_arrow0[2].y = -clipping_arrow0[2].y; clipping_arrow0[3].y = -clipping_arrow0[3].y; clipping_arrow0_offset = -clipping_arrow0_offset; dy_glidebar0 = -1; } for (unsigned i = 0; i < 6; i++) { GlideBar[i].y += y0 + dy_glidebar; GlideBar[i].x = Layout::Scale(GlideBar[i].x) + rc.left; } GlideBar[0].y -= Offset; GlideBar[1].y -= Offset; GlideBar[2].y -= Offset; for (unsigned i = 0; i < 4; i++) { GlideBar0[i].y += y0 + dy_glidebar0; GlideBar0[i].x = Layout::Scale(GlideBar0[i].x) + rc.left; } GlideBar0[0].y -= Offset0; GlideBar0[1].y -= Offset0; if ((altitude_difference0 >= altitude_difference) && (altitude_difference > 0)) { // both above and mc0 arrow larger than mc arrow GlideBar0[2].y = GlideBar[1].y; // both below GlideBar0[3].y = GlideBar[0].y; } // prepare clipping arrow for (unsigned i = 0; i < 6; i++) { clipping_arrow[i].y = Layout::Scale(clipping_arrow[i].y) + y0 - Offset + clipping_arrow_offset + dy_glidebar; clipping_arrow[i].x = Layout::Scale(clipping_arrow[i].x) + rc.left; } // prepare clipping arrow mc0 for (unsigned i = 0; i < 4; i++) { clipping_arrow0[i].y = Layout::Scale(clipping_arrow0[i].y) + y0 - Offset0 + clipping_arrow0_offset + dy_glidebar0; clipping_arrow0[i].x = Layout::Scale(clipping_arrow0[i].x) + rc.left; } // draw actual glide bar if (altitude_difference <= 0) { if (calculated.common_stats.landable_reachable) { canvas.Select(look.pen_below_landable); canvas.Select(look.brush_below_landable); } else { canvas.Select(look.pen_below); canvas.Select(look.brush_below); } } else { canvas.Select(look.pen_above); canvas.Select(look.brush_above); } canvas.DrawPolygon(GlideBar, 6); // draw clipping arrow if ((altitude_difference <= -468 ) || (altitude_difference >= 468)) canvas.DrawPolygon(clipping_arrow, 6); // draw glide bar at mc 0 if (altitude_difference0 <= 0 && final_glide_bar_mc0_enabled) { if (calculated.common_stats.landable_reachable) { canvas.Select(look.pen_below_landable); canvas.Select(look.brush_below_landable_mc0); } else { canvas.Select(look.pen_below); canvas.Select(look.brush_below_mc0); } } else { canvas.Select(look.pen_above); canvas.Select(look.brush_above_mc0); } if ( ( (altitude_difference != altitude_difference0) || (altitude_difference0 < 0) ) && final_glide_bar_mc0_enabled) { canvas.DrawPolygon(GlideBar0, 4); if ((altitude_difference0 <= -468 ) || (altitude_difference0 >= 468)) canvas.DrawPolygon(clipping_arrow0, 4); } // draw cross (x) on final glide bar if unreachable at current Mc // or above final glide but impeded by obstacle int cross_sign = 0; if (!total.IsAchievable()) cross_sign = 1; if (calculated.terrain_warning_location.IsValid() && altitude_difference > 0 ) cross_sign = -1; if (cross_sign != 0) { canvas.Select(task_look.bearing_pen); canvas.DrawLine(Layout::Scale(9 - 5), y0 + cross_sign * Layout::Scale(9 - 5), Layout::Scale(9 + 5), y0 + cross_sign * Layout::Scale(9 + 5)); canvas.DrawLine(Layout::Scale(9 - 5), y0 + cross_sign * Layout::Scale(9 + 5), Layout::Scale(9 + 5), y0 + cross_sign * Layout::Scale(9 - 5)); } canvas.SetTextColor(COLOR_BLACK); canvas.SetBackgroundColor(COLOR_WHITE); TextInBoxMode style; style.shape = LabelShape::ROUNDED_BLACK; style.move_in_view = true; if (text_size.cx < Layout::Scale(18)) { style.align = TextInBoxMode::Alignment::RIGHT; TextInBox(canvas, Value, Layout::Scale(18), y0, style, rc); } else TextInBox(canvas, Value, 0, y0, style, rc); }
result DrawElement(const Osp::Graphics::Canvas& canvas, const Osp::Graphics::Rectangle& rect, CustomListItemStatus itemStatus) { result r = E_SUCCESS; Canvas* pCanvas = const_cast<Canvas*>(&canvas); pCanvas->SetLineWidth(1); if (itemStatus == CUSTOM_LIST_ITEM_STATUS_SELECTED) { pCanvas->FillRectangle(Color(4,58,99), rect); } pCanvas->SetForegroundColor(Color::COLOR_WHITE); Font fontcol1; fontcol1.Construct(Osp::Graphics::FONT_STYLE_PLAIN, 36); Font fontcol2; fontcol2.Construct(Osp::Graphics::FONT_STYLE_PLAIN, 28); Font fontcol3; fontcol3.Construct(Osp::Graphics::FONT_STYLE_PLAIN, 36); Font fontcol4; fontcol4.Construct(Osp::Graphics::FONT_STYLE_PLAIN, 28); EnrichedText texteelcol1; texteelcol1.Construct(Dimension(280, 50)); texteelcol1.SetHorizontalAlignment(Osp::Graphics::TEXT_ALIGNMENT_LEFT); texteelcol1.SetVerticalAlignment(Osp::Graphics::TEXT_ALIGNMENT_TOP); texteelcol1.SetTextAbbreviationEnabled(true); if ((searchq.GetLength() > 0) && (col1s.GetLength() > 0)) { TextElement * textelcol1b = new TextElement(); textelcol1b->Construct(L" "); if (col1b.GetLength() > 0) { textelcol1b->SetText(col1b); textelcol1b->SetTextColor(Color::COLOR_WHITE); textelcol1b->SetFont(fontcol1); texteelcol1.Add(*textelcol1b); } TextElement * textelcol1s = new TextElement(); textelcol1s->Construct(col1s); textelcol1s->SetTextColor(Color(237,255,0)); textelcol1s->SetFont(fontcol1); texteelcol1.Add(*textelcol1s); TextElement * textelcol1a = new TextElement(); textelcol1a->Construct(L" "); if (col1a.GetLength() > 0) { textelcol1a->SetText(col1a); textelcol1a->SetTextColor(Color::COLOR_WHITE); textelcol1a->SetFont(fontcol1); texteelcol1.Add(*textelcol1a); } pCanvas->DrawText(Point(20,15), texteelcol1); delete textelcol1b; delete textelcol1s; delete textelcol1a; } else { TextElement textelcol1; textelcol1.Construct(col1); textelcol1.SetTextColor(Color::COLOR_WHITE); textelcol1.SetFont(fontcol1); texteelcol1.Add(textelcol1); pCanvas->DrawText(Point(20,15), texteelcol1); } EnrichedText texteelcol2; texteelcol2.Construct(Dimension(280, 40)); texteelcol2.SetHorizontalAlignment(Osp::Graphics::TEXT_ALIGNMENT_LEFT); texteelcol2.SetVerticalAlignment(Osp::Graphics::TEXT_ALIGNMENT_TOP); texteelcol2.SetTextAbbreviationEnabled(true); TextElement textelcol2; textelcol2.Construct(col2); if (itemStatus == CUSTOM_LIST_ITEM_STATUS_SELECTED) { textelcol2.SetTextColor(Color::COLOR_WHITE); } else { textelcol2.SetTextColor(Color(10, 73, 136)); } textelcol2.SetFont(fontcol2); texteelcol2.Add(textelcol2); if ((searchq.GetLength() > 0) && (col4.GetLength() > 0)) { pCanvas->DrawText(Point(20,53), texteelcol2); } else { pCanvas->DrawText(Point(20,60), texteelcol2); } EnrichedText texteelcol3; texteelcol3.Construct(Dimension(160, 70)); texteelcol3.SetHorizontalAlignment(Osp::Graphics::TEXT_ALIGNMENT_RIGHT); texteelcol3.SetVerticalAlignment(Osp::Graphics::TEXT_ALIGNMENT_MIDDLE); TextElement textelcol3; textelcol3.Construct(col3); textelcol3.SetTextColor(Color::COLOR_WHITE); textelcol3.SetFont(fontcol3); texteelcol3.Add(textelcol3); pCanvas->DrawText(Point(300,15), texteelcol3); if ((searchq.GetLength() > 0) && (col4.GetLength() > 0)) { EnrichedText texteelcol4; texteelcol4.Construct(Dimension(430, 60)); texteelcol4.SetHorizontalAlignment(Osp::Graphics::TEXT_ALIGNMENT_LEFT); texteelcol4.SetVerticalAlignment(Osp::Graphics::TEXT_ALIGNMENT_TOP); texteelcol4.SetTextAbbreviationEnabled(true); texteelcol4.SetTextWrapStyle(TEXT_WRAP_WORD_WRAP); if ((searchq.GetLength() > 0) && (col4s.GetLength() > 0)) { TextElement * textelcol4b = new TextElement(); textelcol4b->Construct(L" "); if (col4b.GetLength() > 0) { textelcol4b->SetText(col4b); textelcol4b->SetTextColor(Color(220, 220, 220)); textelcol4b->SetFont(fontcol4); texteelcol4.Add(*textelcol4b); } TextElement * textelcol4s = new TextElement(); textelcol4s->Construct(col4s); textelcol4s->SetTextColor(Color(237,255,0)); textelcol4s->SetFont(fontcol4); texteelcol4.Add(*textelcol4s); TextElement * textelcol4a = new TextElement(); textelcol4a->Construct(L" "); if (col4a.GetLength() > 0) { textelcol4a->SetText(col4a); textelcol4a->SetTextColor(Color(220, 220, 220)); textelcol4a->SetFont(fontcol4); texteelcol4.Add(*textelcol4a); } pCanvas->DrawText(Point(20,85), texteelcol4); delete textelcol4b; delete textelcol4s; delete textelcol4a; } else { TextElement textelcol4; textelcol4.Construct(col4); textelcol4.SetTextColor(Color(220, 220, 220)); textelcol4.SetFont(fontcol4); texteelcol4.Add(textelcol4); pCanvas->DrawText(Point(20,85), texteelcol4); } } pCanvas->DrawLine(Point(rect.x, rect.height - 1), Point(rect.width, rect.height - 1)); return r; }
void ThermalAssistantWindow::PaintAdvisor(Canvas &canvas) const { canvas.DrawLine(mid.x, mid.y, lift_point_avg.x, lift_point_avg.y); }
void PaintTask(Canvas &canvas, const WindowProjection &projection, const OrderedTask &task, const GeoPoint &location, const MapSettings &settings_map, const TaskLook &task_look, const AirspaceLook &airspace_look, const RasterTerrain *terrain, const Airspaces *airspaces, bool fai_sectors, int highlight_index) { BackgroundRenderer background; background.SetTerrain(terrain); background.Draw(canvas, projection, settings_map.terrain); if (airspaces != NULL) { AirspaceRenderer airspace_renderer(airspace_look); airspace_renderer.SetAirspaces(airspaces); #ifndef ENABLE_OPENGL BufferCanvas stencil_canvas; stencil_canvas.Create(canvas); #endif airspace_renderer.Draw(canvas, #ifndef ENABLE_OPENGL stencil_canvas, #endif projection, settings_map.airspace); } #ifdef ENABLE_OPENGL /* desaturate the map background, to focus on the task */ canvas.FadeToWhite(0xc0); #endif if (fai_sectors && IsFAITriangleApplicable(task)) { static constexpr Color fill_color = COLOR_YELLOW; #if defined(ENABLE_OPENGL) || defined(USE_MEMORY_CANVAS) #ifdef ENABLE_OPENGL const ScopeAlphaBlend alpha_blend; #endif canvas.Select(Brush(fill_color.WithAlpha(40))); canvas.Select(Pen(1, COLOR_BLACK.WithAlpha(80))); RenderFAISectors(canvas, projection, task); #else BufferCanvas buffer_canvas; buffer_canvas.Create(canvas); buffer_canvas.ClearWhite(); #ifdef HAVE_HATCHED_BRUSH buffer_canvas.Select(airspace_look.brushes[3]); buffer_canvas.SetTextColor(fill_color); buffer_canvas.SetBackgroundColor(COLOR_WHITE); #else buffer_canvas.Select(Brush(fill_color)); #endif buffer_canvas.SelectNullPen(); RenderFAISectors(buffer_canvas, projection, task); canvas.CopyAnd(buffer_canvas); canvas.SelectHollowBrush(); canvas.SelectBlackPen(); RenderFAISectors(canvas, projection, task); #endif } OZRenderer ozv(task_look, airspace_look, settings_map.airspace); TaskPointRenderer tpv(canvas, projection, task_look, task.GetTaskProjection(), ozv, false, TaskPointRenderer::NONE, location); TaskRenderer dv(tpv, projection.GetScreenBounds()); dv.Draw(task); // highlight a task point if (highlight_index >= 0 && highlight_index < (int) task.TaskSize()) { /* TODO: clumsy way of highlighting. maybe it should be done by * painting the task point with a different pen and brush, * e.g. red, 4px wide */ auto pt = projection.GeoToScreen(task.GetPoint(highlight_index). GetLocation()); canvas.Select(task_look.highlight_pen); canvas.DrawLine(pt.x - 7, pt.y - 7, pt.x + 7, pt.y + 7); canvas.DrawLine(pt.x + 7, pt.y - 7, pt.x - 7, pt.y + 7); } }
//------------------------------------------------------------------------------ int main(int argc, char *argv[]) { QApplication app(argc, argv); Canvas c; Pen(Pen::SOLID, 1, Color(0, 0, 0)); { c.Select(Brush(Color(128, 128, 0, Color::TRANSPARENT))); c.DrawKeyhole(200, 100, 50, 100, Angle::Degrees(-20), Angle::Degrees(20)); c.DrawKeyhole(400, 100, 50, 100, Angle::Degrees(70), Angle::Degrees(110)); c.DrawKeyhole(200, 300, 50, 100, Angle::Degrees(160), Angle::Degrees(200)); c.DrawKeyhole(400, 300, 50, 100, Angle::Degrees(-110), Angle::Degrees(-70)); c.show(); app.exec(); } { c.Clear(); c.DrawKeyhole(200, 100, 50, 100, Angle::Degrees(35), Angle::Degrees(55)); c.DrawKeyhole(400, 100, 50, 100, Angle::Degrees(125), Angle::Degrees(145)); c.DrawKeyhole(200, 300, 50, 100, Angle::Degrees(215), Angle::Degrees(235)); c.DrawKeyhole(400, 300, 50, 100, Angle::Degrees(305), Angle::Degrees(325)); c.show(); app.exec(); } { c.Clear(); c.DrawFilledRectangle(0, 0, 100, 100, Color(128, 128, 128, Color::TRANSPARENT)); c.DrawFilledRectangle(100, 100, 200, 200, Color(128, 0, 0, Color::TRANSPARENT)); c.DrawFilledRectangle(150, 150, 250, 250, Color(0, 128, 0, Color::TRANSPARENT)); c.DrawFilledRectangle(200, 200, 300, 300, Color(0, 0, 128, Color::TRANSPARENT)); c.DrawTransparentText(0, 0, "0"); c.DrawTransparentText(0, 100, "100"); c.DrawTransparentText(0, 200, "200"); c.DrawTransparentText(0, 300, "300"); c.DrawTransparentText(0, 400, "400"); c.DrawTransparentText(0, 500, "500"); c.DrawTransparentText(100, c.GetFontHeight(), "100"); c.DrawTransparentText(200, c.GetFontHeight(), "200"); c.DrawTransparentText(300, c.GetFontHeight(), "300"); c.DrawTransparentText(400, c.GetFontHeight(), "400"); c.DrawTransparentText(500, c.GetFontHeight(), "500"); c.show(); app.exec(); } { c.Clear(); c.DrawOutlineRectangle(100, 100, 200, 200, Color(255, 0, 0)); c.show(); app.exec(); } { c.Clear(); c.DrawRoundRectangle(100, 100, 200, 200, 10, 10); c.DrawRoundRectangle(200, 200, 300, 300, 100, 100); c.DrawRoundRectangle(300, 300, 400, 400, 50, 50); c.show(); app.exec(); } { c.Clear(); PixelRect rc; rc.left = 100; rc.top = 100; rc.right = 200; rc.bottom = 200; c.DrawRaisedEdge(rc); c.show(); app.exec(); } { c.Clear(); RasterPoint rp[4]; rp[0] = {100, 100}; rp[1] = {200, 200}; rp[2] = {200, 300}; rp[3] = {300, 400}; c.DrawPolyline(rp, 4); c.show(); app.exec(); } { c.Clear(); RasterPoint rp[6]; rp[0] = {100, 100}; rp[1] = {150, 50}; rp[2] = {200, 100}; rp[3] = {200, 200}; rp[4] = {150, 200}; rp[5] = {100, 100}; c.DrawPolygon(rp, 6); c.show(); app.exec(); } { c.Clear(); RasterPoint rp[4]; rp[0] = {100, 100}; rp[1] = {200, 50}; rp[2] = {200, 150}; rp[3] = {150, 200}; c.DrawTriangleFan(rp, 4); c.show(); app.exec(); } { c.Clear(); c.DrawHLine(100, 200, 100, Color(255, 0, 0)); c.DrawHLine(100, 200, 200, Color(0, 255, 0)); c.DrawHLine(100, 200, 300, Color(0, 0, 255)); c.show(); app.exec(); } { c.Clear(); c.DrawLine(100, 100, 200, 200); c.DrawCircle(250, 250, 50); c.DrawSegment(100, 250, 50, Angle::Degrees(10), Angle::Degrees(30), false); c.show(); app.exec(); } { c.Clear(); c.DrawAnnulus(100, 100, 50, 100, Angle::Degrees(10), Angle::Degrees(60)); c.DrawAnnulus(300, 100, 50, 100, Angle::Degrees(0), Angle::Degrees(360)); c.DrawAnnulus(100, 300, 50, 100, Angle::Degrees(0), Angle::Degrees(0)); c.show(); app.exec(); } { PixelSize rc = c.CalcTextSize("Hello"); std::cout << "Size of \"Hello\": " << rc.cx << ", " << rc.cy << std::endl; c.DrawClippedText(100, 100, rc.cx / 2, "Hello"); c.show(); app.exec(); } { std::cout << "Height of font: " << c.GetFontHeight() << std::endl; } { c.Clear(); c.DrawText(0, 50, "50"); c.Clear(); c.show(); return app.exec(); } }
void TrailRenderer::Draw(Canvas &canvas, const TraceComputer &trace_computer, const WindowProjection &projection, unsigned min_time, bool enable_traildrift, const RasterPoint pos, const NMEAInfo &basic, const DerivedInfo &calculated, const TrailSettings &settings) { if (settings.length == TrailSettings::Length::OFF) return; if (!LoadTrace(trace_computer, min_time, projection)) return; if (!calculated.wind_available) enable_traildrift = false; GeoPoint traildrift; if (enable_traildrift) { GeoPoint tp1 = FindLatitudeLongitude(basic.location, calculated.wind.bearing, calculated.wind.norm); traildrift = basic.location - tp1; } fixed value_max, value_min; GetMinMax(value_min, value_max, settings.type, trace); bool scaled_trail = settings.scaling_enabled && projection.GetMapScale() <= fixed_int_constant(6000); const GeoBounds bounds = projection.GetScreenBounds().Scale(fixed_four); RasterPoint last_point; bool last_valid = false; for (auto it = trace.begin(), end = trace.end(); it != end; ++it) { const GeoPoint gp = enable_traildrift ? it->GetLocation().Parametric(traildrift, it->CalculateDrift(basic.time)) : it->GetLocation(); if (!bounds.IsInside(gp)) { /* the point is outside of the MapWindow; don't paint it */ last_valid = false; continue; } RasterPoint pt = projection.GeoToScreen(gp); if (last_valid) { if (settings.type == TrailSettings::Type::ALTITUDE) { unsigned index((it->GetAltitude() - value_min) / (value_max - value_min) * (TrailLook::NUMSNAILCOLORS - 1)); index = max(0u, min(TrailLook::NUMSNAILCOLORS - 1, index)); canvas.Select(look.trail_pens[index]); canvas.DrawLinePiece(last_point, pt); } else { const fixed colour_vario = negative(it->GetVario()) ? - it->GetVario() / value_min : it->GetVario() / value_max ; unsigned color_index = GetSnailColorIndex(colour_vario); if (negative(it->GetVario()) && (settings.type == TrailSettings::Type::VARIO_1_DOTS || settings.type == TrailSettings::Type::VARIO_2_DOTS)) { canvas.SelectNullPen(); canvas.Select(look.trail_brushes[color_index]); canvas.DrawCircle((pt.x + last_point.x) / 2, (pt.y + last_point.y) / 2, look.trail_widths[color_index]); } else { if (!scaled_trail) canvas.Select(look.trail_pens[color_index]); else canvas.Select(look.scaled_trail_pens[color_index]); canvas.DrawLinePiece(last_point, pt); } } } last_point = pt; last_valid = true; } if (last_valid) canvas.DrawLine(last_point, pos); }