void ButtonFrameRenderer::DrawButton(Canvas &canvas, PixelRect rc, bool focused, bool pressed) const { const ButtonLook::StateLook &_look = focused ? look.focused : look.standard; canvas.DrawFilledRectangle(rc, _look.background_color); const unsigned margin = GetMargin(); if (margin < 4) { /* draw 1-pixel lines */ canvas.Select(pressed ? _look.dark_border_pen : _look.light_border_pen); for (unsigned i = 0; i < margin; ++i) canvas.DrawTwoLinesExact(rc.left + i, rc.bottom - 2 - i, rc.left + i, rc.top + i, rc.right - 2 - i, rc.top + i); canvas.Select(pressed ? _look.light_border_pen : _look.dark_border_pen); for (unsigned i = 0; i < margin; ++i) canvas.DrawTwoLinesExact(rc.left + 1 + i, rc.bottom - 1 - i, rc.right - 1 - i, rc.bottom - 1 - i, rc.right - 1 - i, rc.top + 1 + i); } else { /* at 4 pixels or more, it's more efficient to draw a filled polygon */ const RasterPoint p1[] = { RasterPoint(rc.left, rc.top), RasterPoint(rc.right, rc.top), RasterPoint(rc.right - margin, rc.top + margin), RasterPoint(rc.left + margin, rc.top + margin), RasterPoint(rc.left + margin, rc.bottom - margin), RasterPoint(rc.left, rc.bottom), }; canvas.SelectNullPen(); canvas.Select(pressed ? _look.dark_border_brush : _look.light_border_brush); canvas.DrawTriangleFan(p1, ARRAY_SIZE(p1)); const RasterPoint p2[] = { RasterPoint(rc.right, rc.bottom), RasterPoint(rc.right, rc.top), RasterPoint(rc.right - margin, rc.top + margin), RasterPoint(rc.right - margin, rc.bottom - margin), RasterPoint(rc.left + margin, rc.bottom - margin), RasterPoint(rc.left, rc.bottom), }; canvas.Select(pressed ? _look.light_border_brush : _look.dark_border_brush); canvas.DrawTriangleFan(p2, ARRAY_SIZE(p2)); } }
void SymbolRenderer::DrawArrow(Canvas &canvas, PixelRect rc, Direction direction) { assert(direction == UP || direction == DOWN || direction == LEFT || direction == RIGHT); PixelScalar size = std::min(rc.right - rc.left, rc.bottom - rc.top) / 5; RasterPoint center = rc.GetCenter(); RasterPoint arrow[3]; if (direction == LEFT || direction == RIGHT) { arrow[0].x = center.x + (direction == LEFT ? size : -size); arrow[0].y = center.y + size; arrow[1].x = center.x + (direction == LEFT ? -size : size); arrow[1].y = center.y; arrow[2].x = center.x + (direction == LEFT ? size : -size); arrow[2].y = center.y - size; } else if (direction == UP || direction == DOWN) { arrow[0].x = center.x + size; arrow[0].y = center.y + (direction == UP ? size : -size); arrow[1].x = center.x; arrow[1].y = center.y + (direction == UP ? -size : size); arrow[2].x = center.x - size; arrow[2].y = center.y + (direction == UP ? size : -size); } canvas.DrawTriangleFan(arrow, 3); }
bool Segment(Canvas &canvas, PixelScalar x, PixelScalar y, UPixelScalar radius, Angle start, Angle end, bool horizon) { // dont draw if out of view PixelRect rc, bounds; SetRect(&rc, 0, 0, canvas.get_width(), canvas.get_height()); SetRect(&bounds, x - radius, y - radius, x + radius, y + radius); if (!IntersectRect(&bounds, &bounds, &rc)) return false; const int istart = NATIVE_TO_INT(start.Native()); const int iend = NATIVE_TO_INT(end.Native()); int npoly = 0; RasterPoint pt[66]; // add center point if (!horizon) { pt[0].x = x; pt[0].y = y; npoly = 1; } segment_poly(pt, x, y, radius, istart, iend, npoly); assert(npoly <= 66); if (npoly) canvas.DrawTriangleFan(pt, npoly); return true; }
void RoundRect(Canvas &canvas, int left, int top, int right, int bottom, unsigned radius) { unsigned npoly = 0; BulkPixelPoint pt[66*4]; segment_poly(pt, PixelPoint(left + radius, top + radius), radius, INT_ANGLE_RANGE * 3 / 4, INT_ANGLE_RANGE - 1, npoly); segment_poly(pt, PixelPoint(right - radius, top + radius), radius, 0, INT_ANGLE_RANGE / 4 - 1, npoly); segment_poly(pt, PixelPoint(right - radius, bottom - radius), radius, INT_ANGLE_RANGE / 4, INT_ANGLE_RANGE / 2 - 1, npoly); segment_poly(pt, PixelPoint(left + radius, bottom - radius), radius, INT_ANGLE_RANGE / 2, INT_ANGLE_RANGE * 3 / 4 - 1, npoly); assert(npoly <= ARRAY_SIZE(pt)); if (npoly) canvas.DrawTriangleFan(pt, npoly); }
void GaugeVario::RenderVarioLine(Canvas &canvas, int i, int sink, bool clear) { dirty = true; if (i == sink) return; canvas.Select(clear ? look.thick_background_pen : (i > sink ? look.thick_lift_pen : look.thick_sink_pen)); if (i > sink) canvas.DrawPolyline(lines + gmax + sink, i - sink); else canvas.DrawPolyline(lines + gmax + i, sink - i); if (!clear) { canvas.SelectNullPen(); // clear up naked (sink) edge of polygon, this gives it a nice // taper look if (look.inverse) { canvas.SelectBlackBrush(); } else { canvas.SelectWhiteBrush(); } canvas.DrawTriangleFan(getPolygon(sink), 3); } }
void SymbolRenderer::DrawArrow(Canvas &canvas, PixelRect rc, Direction direction) { assert(direction == UP || direction == DOWN || direction == LEFT || direction == RIGHT); auto size = std::min(rc.GetWidth(), rc.GetHeight()) / 5; auto center = rc.GetCenter(); BulkPixelPoint arrow[3]; if (direction == LEFT || direction == RIGHT) { arrow[0].x = center.x + (direction == LEFT ? size : -size); arrow[0].y = center.y + size; arrow[1].x = center.x + (direction == LEFT ? -size : size); arrow[1].y = center.y; arrow[2].x = center.x + (direction == LEFT ? size : -size); arrow[2].y = center.y - size; } else if (direction == UP || direction == DOWN) { arrow[0].x = center.x + size; arrow[0].y = center.y + (direction == UP ? size : -size); arrow[1].x = center.x; arrow[1].y = center.y + (direction == UP ? -size : size); arrow[2].x = center.x - size; arrow[2].y = center.y + (direction == UP ? size : -size); } canvas.DrawTriangleFan(arrow, 3); }
static void DrawLandableRunway(Canvas &canvas, const PixelPoint &pt, const Angle angle, double radius, double width) { if (radius <= 0) return; const auto sc = angle.SinCos(); const auto x = sc.first, y = sc.second; int lx = iround(2 * x * radius) & ~0x1; // make it a even number int ly = iround(2 * y * radius) & ~0x1; int wx = iround(-y * width); int wy = iround(x * width); BulkPixelPoint runway[4]; runway[0].x = pt.x - (lx / 2) + (wx / 2); runway[0].y = pt.y + (ly / 2) - (wy / 2); runway[1].x = runway[0].x - wx; runway[1].y = runway[0].y + wy; runway[2].x = runway[1].x + lx; runway[2].y = runway[1].y - ly; runway[3].x = runway[2].x + wx; runway[3].y = runway[2].y - wy; canvas.DrawTriangleFan(runway, ARRAY_SIZE(runway)); }
bool Segment(Canvas &canvas, int x, int y, unsigned radius, Angle start, Angle end, bool horizon) { // dont draw if out of view if (!IsCircleVisible(canvas, x, y, radius)) return false; const int istart = NATIVE_TO_INT(start.Native()); const int iend = NATIVE_TO_INT(end.Native()); unsigned npoly = 0; RasterPoint pt[67]; // add center point if (!horizon) { pt[0].x = x; pt[0].y = y; npoly = 1; } segment_poly(pt, x, y, radius, istart, iend, npoly); assert(npoly <= ARRAY_SIZE(pt)); if (npoly) canvas.DrawTriangleFan(pt, npoly); return true; }
void TopWindow::OnPaint(Canvas &canvas) { ContainerWindow::OnPaint(canvas); /* draw the mouse cursor */ const RasterPoint m = event_queue->GetMousePosition(); const RasterPoint p[] = { { m.x, m.y }, { m.x + Layout::Scale(4), m.y + Layout::Scale(4) }, { m.x, m.y + Layout::Scale(6) }, }; canvas.SelectBlackPen(); canvas.SelectWhiteBrush(); canvas.DrawTriangleFan(p, ARRAY_SIZE(p)); }
void CrossSectionWindow::PaintAircraft(Canvas &canvas, const Chart &chart, const PixelRect rc) { canvas.Select(look.aircraft_brush); canvas.SelectNullPen(); RasterPoint line[4]; line[0].x = chart.screenX(fixed_zero); line[0].y = chart.screenY(gps_info.nav_altitude); line[1].x = rc.left; line[1].y = line[0].y; line[2].x = line[1].x; line[2].y = line[0].y - (line[0].x - line[1].x) / 2; line[3].x = (line[1].x + line[0].x) / 2; line[3].y = line[0].y; canvas.DrawTriangleFan(line, 4); }
void GaugeVario::RenderNeedle(Canvas &canvas, int i, bool average, bool clear) { dirty = true; canvas.SelectNullPen(); // legacy behaviour if (clear ^ look.inverse) { canvas.SelectWhiteBrush(); } else { canvas.SelectBlackBrush(); } if (average) canvas.DrawPolyline(getPolygon(i), 3); else canvas.DrawTriangleFan(getPolygon(i), 3); }
static void DrawLandableBase(Canvas &canvas, const PixelPoint &pt, bool airport, const double radius) { int iradius = iround(radius); if (airport) canvas.DrawCircle(pt.x, pt.y, iradius); else { BulkPixelPoint diamond[4]; diamond[0].x = pt.x + 0; diamond[0].y = pt.y - iradius; diamond[1].x = pt.x + iradius; diamond[1].y = pt.y + 0; diamond[2].x = pt.x + 0; diamond[2].y = pt.y + iradius; diamond[3].x = pt.x - iradius; diamond[3].y = pt.y - 0; canvas.DrawTriangleFan(diamond, ARRAY_SIZE(diamond)); } }
void CrossSectionRenderer::PaintAircraft(Canvas &canvas, const ChartRenderer &chart, const PixelRect rc) const { if (!gps_info.NavAltitudeAvailable()) return; canvas.Select(look.aircraft_brush); canvas.SelectNullPen(); RasterPoint line[4]; line[0] = chart.ToScreen(fixed(0), gps_info.nav_altitude); line[1].x = rc.left; line[1].y = line[0].y; line[2].x = line[1].x; line[2].y = line[0].y - (line[0].x - line[1].x) / 2; line[3].x = (line[1].x + line[0].x) / 2; line[3].y = line[0].y; canvas.DrawTriangleFan(line, 4); }
void GaugeVario::RenderSpeedToFly(Canvas &canvas, int x, int y) { if (!Basic().airspeed_available || !Basic().total_energy_vario_available) return; static fixed last_v_diff; fixed v_diff; const unsigned arrow_y_size = Layout::Scale(3); const unsigned arrow_x_size = Layout::Scale(7); const PixelRect rc = GetClientRect(); int nary = NARROWS * arrow_y_size; int ytop = rc.top + YOFFSET + nary; // JMW int ybottom = rc.bottom - YOFFSET - nary - Layout::FastScale(1); ytop += Layout::Scale(14); ybottom -= Layout::Scale(14); x = rc.right - 2 * arrow_x_size; // only draw speed command if flying and vario is not circling if ((Calculated().flight.flying) && (!Basic().gps.simulator || !Calculated().circling)) { v_diff = Calculated().V_stf - Basic().indicated_airspeed; v_diff = Clamp(v_diff, -DELTA_V_LIMIT, DELTA_V_LIMIT); // limit it v_diff = iround(v_diff/DELTA_V_STEP) * DELTA_V_STEP; } else v_diff = fixed(0); if (!IsPersistent() || last_v_diff != v_diff || dirty) { last_v_diff = v_diff; if (IsPersistent()) { // bottom (too slow) canvas.DrawFilledRectangle(x, ybottom + YOFFSET, x + arrow_x_size * 2 + 1, ybottom + YOFFSET + nary + arrow_y_size + Layout::FastScale(2), look.background_color); // top (too fast) canvas.DrawFilledRectangle(x, ytop - YOFFSET + 1, x + arrow_x_size * 2 +1, ytop - YOFFSET - nary + 1 - arrow_y_size - Layout::FastScale(2), look.background_color); } RenderClimb(canvas); canvas.SelectNullPen(); if (look.colors) { if (positive(v_diff)) { // too slow canvas.Select(look.sink_brush); } else { canvas.Select(look.lift_brush); } } else { if (look.inverse) canvas.SelectWhiteBrush(); else canvas.SelectBlackBrush(); } if (positive(v_diff)) { // too slow y = ybottom; y += YOFFSET; while (positive(v_diff)) { if (v_diff > DELTA_V_STEP) { canvas.Rectangle(x, y, x + arrow_x_size * 2 + 1, y + arrow_y_size - 1); } else { RasterPoint arrow[3]; arrow[0].x = x; arrow[0].y = y; arrow[1].x = x + arrow_x_size; arrow[1].y = y + arrow_y_size - 1; arrow[2].x = x + 2 * arrow_x_size; arrow[2].y = y; canvas.DrawTriangleFan(arrow, 3); } v_diff -= DELTA_V_STEP; y += arrow_y_size; } } else if (negative(v_diff)) { // too fast y = ytop; y -= YOFFSET; while (negative(v_diff)) { if (v_diff < -DELTA_V_STEP) { canvas.Rectangle(x, y + 1, x + arrow_x_size * 2 + 1, y - arrow_y_size + 2); } else { RasterPoint arrow[3]; arrow[0].x = x; arrow[0].y = y; arrow[1].x = x + arrow_x_size; arrow[1].y = y - arrow_y_size + 1; arrow[2].x = x + 2 * arrow_x_size; arrow[2].y = y; canvas.DrawTriangleFan(arrow, 3); } v_diff += DELTA_V_STEP; y -= arrow_y_size; } } } }
void GaugeVario::RenderSpeedToFly(Canvas &canvas, PixelScalar x, PixelScalar y) { if (!Basic().airspeed_available || !Basic().total_energy_vario_available) return; static fixed lastVdiff; fixed vdiff; const UPixelScalar arrow_y_size = Layout::Scale(3); const UPixelScalar arrow_x_size = Layout::Scale(7); const PixelRect rc = get_client_rect(); PixelScalar nary = NARROWS * arrow_y_size; PixelScalar ytop = rc.top + YOFFSET + nary; // JMW PixelScalar ybottom = rc.bottom - YOFFSET - nary - Layout::FastScale(1); ytop += Layout::Scale(14); ybottom -= Layout::Scale(14); x = rc.right - 2 * arrow_x_size; // only draw speed command if flying and vario is not circling if ((Calculated().flight.flying) && (!Basic().gps.simulator || !Calculated().circling)) { vdiff = Calculated().V_stf - Basic().indicated_airspeed; vdiff = max(-DeltaVlimit, min(DeltaVlimit, vdiff)); // limit it vdiff = iround(vdiff/DeltaVstep) * DeltaVstep; } else vdiff = fixed_zero; if (!is_persistent() || lastVdiff != vdiff || dirty) { lastVdiff = vdiff; if (is_persistent()) { // bottom (too slow) canvas.DrawFilledRectangle(x, ybottom + YOFFSET, x + arrow_x_size * 2 + 1, ybottom + YOFFSET + nary + arrow_y_size + Layout::FastScale(2), look.background_color); // top (too fast) canvas.DrawFilledRectangle(x, ytop - YOFFSET + 1, x + arrow_x_size * 2 +1, ytop - YOFFSET - nary + 1 - arrow_y_size - Layout::FastScale(2), look.background_color); } RenderClimb(canvas); canvas.SelectNullPen(); if (look.colors) { if (positive(vdiff)) { // too slow canvas.Select(look.sink_brush); } else { canvas.Select(look.lift_brush); } } else { if (look.inverse) canvas.SelectWhiteBrush(); else canvas.SelectBlackBrush(); } if (positive(vdiff)) { // too slow y = ybottom; y += YOFFSET; while (positive(vdiff)) { if (vdiff > DeltaVstep) { canvas.Rectangle(x, y, x + arrow_x_size * 2 + 1, y + arrow_y_size - 1); } else { RasterPoint arrow[3]; arrow[0].x = x; arrow[0].y = y; arrow[1].x = x + arrow_x_size; arrow[1].y = y + arrow_y_size - 1; arrow[2].x = x + 2 * arrow_x_size; arrow[2].y = y; canvas.DrawTriangleFan(arrow, 3); } vdiff -= DeltaVstep; y += arrow_y_size; } } else if (negative(vdiff)) { // too fast y = ytop; y -= YOFFSET; while (negative(vdiff)) { if (vdiff < -DeltaVstep) { canvas.Rectangle(x, y + 1, x + arrow_x_size * 2 + 1, y - arrow_y_size + 2); } else { RasterPoint arrow[3]; arrow[0].x = x; arrow[0].y = y; arrow[1].x = x + arrow_x_size; arrow[1].y = y - arrow_y_size + 1; arrow[2].x = x + 2 * arrow_x_size; arrow[2].y = y; canvas.DrawTriangleFan(arrow, 3); } vdiff += DeltaVstep; y -= arrow_y_size; } } } }
void ScrollBar::Paint(Canvas &canvas) const { // ################### // #### ScrollBar #### // ################### // draw rectangle around entire scrollbar area canvas.SelectBlackPen(); canvas.SelectHollowBrush(); canvas.Rectangle(rc.left, rc.top, rc.right, rc.bottom); // ################### // #### Buttons #### // ################### const int arrow_padding = std::max(GetWidth() / 4, 4); PixelRect up_arrow_rect = rc; ++up_arrow_rect.left; up_arrow_rect.bottom = up_arrow_rect.top + GetWidth(); PixelRect down_arrow_rect = rc; ++down_arrow_rect.left; down_arrow_rect.top = down_arrow_rect.bottom - GetWidth(); canvas.DrawExactLine(up_arrow_rect.left, up_arrow_rect.bottom, up_arrow_rect.right, up_arrow_rect.bottom); canvas.DrawExactLine(down_arrow_rect.left, down_arrow_rect.top - 1, down_arrow_rect.right, down_arrow_rect.top - 1); button_renderer.DrawButton(canvas, up_arrow_rect, false, false); button_renderer.DrawButton(canvas, down_arrow_rect, false, false); canvas.SelectNullPen(); canvas.SelectBlackBrush(); const RasterPoint up_arrow[3] = { { (up_arrow_rect.left + rc.right) / 2, up_arrow_rect.top + arrow_padding }, { up_arrow_rect.left + arrow_padding, up_arrow_rect.bottom - arrow_padding }, { rc.right - arrow_padding, up_arrow_rect.bottom - arrow_padding }, }; canvas.DrawTriangleFan(up_arrow, ARRAY_SIZE(up_arrow)); const RasterPoint down_arrow[3] = { { (down_arrow_rect.left + rc.right) / 2, down_arrow_rect.bottom - arrow_padding }, { down_arrow_rect.left + arrow_padding, down_arrow_rect.top + arrow_padding }, { rc.right - arrow_padding, down_arrow_rect.top + arrow_padding }, }; canvas.DrawTriangleFan(down_arrow, ARRAY_SIZE(down_arrow)); // ################### // #### Slider #### // ################### if (rc_slider.top + 4 < rc_slider.bottom) { canvas.SelectBlackPen(); canvas.DrawExactLine(rc_slider.left, rc_slider.top, rc_slider.right, rc_slider.top); canvas.DrawExactLine(rc_slider.left, rc_slider.bottom, rc_slider.right, rc_slider.bottom); PixelRect rc_slider2 = rc_slider; ++rc_slider2.left; ++rc_slider2.top; button_renderer.DrawButton(canvas, rc_slider2, dragging, dragging); } // fill the rest with darker gray const Color background_color = IsDithered() ? COLOR_BLACK : COLOR_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, background_color); if (rc_slider.bottom + 1 < down_arrow_rect.top - 1) canvas.DrawFilledRectangle(rc.left + 1, rc_slider.bottom + 1, rc.right, down_arrow_rect.top - 1, background_color); }
/** * Paints the traffic symbols on the given canvas * @param canvas The canvas to paint on */ void FlarmTrafficWindow::PaintRadarTarget(Canvas &canvas, const FlarmTraffic &traffic, unsigned i) { // Save relative East/North fixed x = traffic.relative_east; fixed y = -traffic.relative_north; // Calculate the distance in pixels fixed scale = RangeScale(traffic.distance); // Don't display distracting, far away targets in WarningMode if (WarningMode() && !traffic.HasAlarm() && scale == fixed(radius)) return; // x and y are not between 0 and 1 (distance will be handled via scale) if (!traffic.distance.IsZero()) { x /= traffic.distance; y /= traffic.distance; } else { x = fixed_zero; y = fixed_zero; } if (!enable_north_up) { // Rotate x and y to have a track up display FastRotation::Pair p = fr.Rotate(x, y); x = fixed(p.first); y = fixed(p.second); } // Calculate screen coordinates sc[i].x = radar_mid.x + iround(x * scale); sc[i].y = radar_mid.y + iround(y * scale); const Color *text_color; const Pen *target_pen, *circle_pen; const Brush *target_brush, *arrow_brush; bool hollow_brush = false; unsigned circles = 0; // Set the arrow color depending on alarm level switch (traffic.alarm_level) { case FlarmTraffic::AlarmType::LOW: text_color = &look.default_color; target_pen = circle_pen = &look.warning_pen; target_brush = &look.warning_brush; arrow_brush = &look.default_brush; circles = 1; break; case FlarmTraffic::AlarmType::IMPORTANT: case FlarmTraffic::AlarmType::URGENT: text_color = &look.default_color; target_pen = circle_pen = &look.alarm_pen; target_brush = &look.alarm_brush; arrow_brush = &look.default_brush; circles = 2; break; case FlarmTraffic::AlarmType::NONE: if (WarningMode()) { text_color = &look.passive_color; target_pen = &look.passive_pen; arrow_brush = &look.passive_brush; hollow_brush = true; } else { // Search for team color FlarmFriends::Color team_color = FlarmFriends::GetFriendColor(traffic.id); // If no color found but target is teammate if (team_color == FlarmFriends::NONE && settings.team_flarm_tracking && traffic.id == settings.team_flarm_id) // .. use yellow color team_color = FlarmFriends::GREEN; // If team color found -> draw a colored circle around the target if (team_color != FlarmFriends::NONE) { switch (team_color) { case FlarmFriends::GREEN: circle_pen = &look.team_pen_green; break; case FlarmFriends::BLUE: circle_pen = &look.team_pen_blue; break; case FlarmFriends::YELLOW: circle_pen = &look.team_pen_yellow; break; case FlarmFriends::MAGENTA: circle_pen = &look.team_pen_magenta; break; default: break; } circles = 1; } if (!small && static_cast<unsigned> (selection) == i) { text_color = &look.selection_color; target_brush = arrow_brush = &look.selection_brush; target_pen = &look.selection_pen; } else { hollow_brush = true; if (traffic.IsPassive()) { text_color = &look.passive_color; target_pen = &look.passive_pen; arrow_brush = &look.passive_brush; } else { text_color = &look.default_color; target_pen = &look.default_pen; arrow_brush = &look.default_brush; } } } break; } if (circles > 0) { canvas.SelectHollowBrush(); canvas.Select(*circle_pen); canvas.circle(sc[i].x, sc[i].y, Layout::FastScale(small ? 8 : 16)); if (circles == 2) canvas.circle(sc[i].x, sc[i].y, Layout::FastScale(small ? 10 : 19)); } // Create an arrow polygon RasterPoint Arrow[5]; if (small) { Arrow[0].x = -3; Arrow[0].y = 4; Arrow[1].x = 0; Arrow[1].y = -5; Arrow[2].x = 3; Arrow[2].y = 4; Arrow[3].x = 0; Arrow[3].y = 2; Arrow[4].x = -3; Arrow[4].y = 4; } else { Arrow[0].x = -6; Arrow[0].y = 8; Arrow[1].x = 0; Arrow[1].y = -10; Arrow[2].x = 6; Arrow[2].y = 8; Arrow[3].x = 0; Arrow[3].y = 5; Arrow[4].x = -6; Arrow[4].y = 8; } // Rotate and shift the arrow PolygonRotateShift(Arrow, 5, sc[i].x, sc[i].y, traffic.track - (enable_north_up ? Angle::Zero() : heading)); // Select pen and brush canvas.Select(*target_pen); if (hollow_brush) canvas.SelectHollowBrush(); else canvas.Select(*target_brush); // Draw the polygon canvas.polygon(Arrow, 5); if (small) { if (WarningMode() && !traffic.HasAlarm()) return; const short relalt = iround(Units::ToUserAltitude(traffic.relative_altitude) / 100); // if (relative altitude is other than zero) if (relalt == 0) return; // Write the relativ altitude devided by 100 to the Buffer StaticString<10> buffer; buffer.Format(_T("%d"), abs(relalt)); // Select font canvas.SetBackgroundTransparent(); canvas.Select(look.side_info_font); canvas.SetTextColor(*text_color); // Calculate size of the output string PixelSize tsize = canvas.CalcTextSize(buffer); UPixelScalar dist = Layout::FastScale(traffic.HasAlarm() ? 12 : 8); // Draw string canvas.text(sc[i].x + dist, sc[i].y - tsize.cy / 2, buffer); // Set target_brush for the up/down arrow canvas.Select(*arrow_brush); canvas.SelectNullPen(); // Prepare the triangular polygon RasterPoint triangle[4]; triangle[0].x = 0; triangle[0].y = -4; triangle[1].x = 3; triangle[1].y = 0; triangle[2].x = -3; triangle[2].y = 0; // Flip = -1 for arrow pointing downwards short flip = 1; if (relalt < 0) flip = -1; // Shift the arrow to the right position for (int j = 0; j < 3; j++) { triangle[j].x = Layout::FastScale(triangle[j].x); triangle[j].y = Layout::FastScale(triangle[j].y); triangle[j].x = sc[i].x + dist + triangle[j].x + tsize.cx / 2; triangle[j].y = sc[i].y + flip * (triangle[j].y - tsize.cy / 2); } triangle[3].x = triangle[0].x; triangle[3].y = triangle[0].y; // Draw the arrow canvas.DrawTriangleFan(triangle, 4); return; } // if warning exists -> don't draw vertical speeds if (WarningMode()) return; // if vertical speed to small or negative -> skip this one if (side_display_type == 1 && (!traffic.climb_rate_avg30s_available || traffic.climb_rate_avg30s < fixed(0.5) || traffic.IsPowered())) return; // Select font canvas.SetBackgroundTransparent(); canvas.Select(look.side_info_font); // Format string TCHAR tmp[10]; if (side_display_type == 1) FormatUserVerticalSpeed(traffic.climb_rate_avg30s, tmp, false); else FormatRelativeUserAltitude(traffic.relative_altitude, tmp, true); PixelSize sz = canvas.CalcTextSize(tmp); // Draw vertical speed shadow canvas.SetTextColor(COLOR_WHITE); canvas.text(sc[i].x + Layout::FastScale(11) + 1, sc[i].y - sz.cy / 2 + 1, tmp); canvas.text(sc[i].x + Layout::FastScale(11) - 1, sc[i].y - sz.cy / 2 - 1, tmp); // Select color canvas.SetTextColor(*text_color); // Draw vertical speed canvas.text(sc[i].x + Layout::FastScale(11), sc[i].y - sz.cy / 2, tmp); }
void FlarmTrafficWindow::PaintTargetInfoSmall( Canvas &canvas, const FlarmTraffic &traffic, unsigned i, const Color &text_color, const Brush &arrow_brush) { const short relalt = iround(Units::ToUserAltitude(traffic.relative_altitude) / 100); // if (relative altitude is other than zero) if (relalt == 0) return; // Write the relativ altitude devided by 100 to the Buffer StaticString<10> buffer; buffer.Format(_T("%d"), abs(relalt)); // Select font canvas.SetBackgroundTransparent(); canvas.Select(look.side_info_font); canvas.SetTextColor(text_color); // Calculate size of the output string PixelSize tsize = canvas.CalcTextSize(buffer); UPixelScalar dist = Layout::FastScale(traffic.HasAlarm() ? 12 : 8); // Draw string canvas.DrawText(sc[i].x + dist, sc[i].y - tsize.cy / 2, buffer); // Set target_brush for the up/down arrow canvas.Select(arrow_brush); canvas.SelectNullPen(); // Prepare the triangular polygon RasterPoint triangle[4]; triangle[0].x = 0; triangle[0].y = -4; triangle[1].x = 3; triangle[1].y = 0; triangle[2].x = -3; triangle[2].y = 0; // Flip = -1 for arrow pointing downwards short flip = 1; if (relalt < 0) flip = -1; // Shift the arrow to the right position for (int j = 0; j < 3; j++) { triangle[j].x = Layout::FastScale(triangle[j].x); triangle[j].y = Layout::FastScale(triangle[j].y); triangle[j].x = sc[i].x + dist + triangle[j].x + tsize.cx / 2; triangle[j].y = sc[i].y + flip * (triangle[j].y - tsize.cy / 2); } triangle[3].x = triangle[0].x; triangle[3].y = triangle[0].y; // Draw the arrow canvas.DrawTriangleFan(triangle, 4); }
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); }
//------------------------------------------------------------------------------ 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 WndSymbolButton::OnPaint(Canvas &canvas) { PixelRect rc = { PixelScalar(0), PixelScalar(0), PixelScalar(canvas.get_width()), PixelScalar(canvas.get_height()) }; bool pressed = is_down(); renderer.DrawButton(canvas, rc, HasFocus(), pressed); // If button has text on it tstring caption = get_text(); if (caption.empty()) return; rc = renderer.GetDrawingRect(rc, pressed); canvas.SelectNullPen(); if (!IsEnabled()) canvas.Select(look.button.disabled.brush); else if (HasFocus()) canvas.Select(look.button.focused.foreground_brush); else canvas.Select(look.button.standard.foreground_brush); const char ch = (char)caption[0]; // Draw arrow symbols instead of < and > if (ch == '<' || ch == '>') { int size = min(rc.right - rc.left, rc.bottom - rc.top) / 5; RasterPoint Arrow[3]; Arrow[0].x = (rc.left + rc.right) / 2 + (ch == '<' ? size : -size); Arrow[0].y = (rc.top + rc.bottom) / 2 + size; Arrow[1].x = (rc.left + rc.right) / 2 + (ch == '<' ? -size : size); Arrow[1].y = (rc.top + rc.bottom) / 2; Arrow[2].x = (rc.left + rc.right) / 2 + (ch == '<' ? size : -size); Arrow[2].y = (rc.top + rc.bottom) / 2 - size; canvas.DrawTriangleFan(Arrow, 3); } // Draw arrow symbols instead of v and ^ else if (ch == '^' || ch == 'v') { int size = min(rc.right - rc.left, rc.bottom - rc.top) / 5; RasterPoint Arrow[3]; Arrow[0].x = (rc.left + rc.right) / 2 + size; Arrow[0].y = (rc.top + rc.bottom) / 2 + (ch == '^' ? size : -size); Arrow[1].x = (rc.left + rc.right) / 2; Arrow[1].y = (rc.top + rc.bottom) / 2 + (ch == '^' ? -size : size); Arrow[2].x = (rc.left + rc.right) / 2 - size; Arrow[2].y = (rc.top + rc.bottom) / 2 + (ch == '^' ? size : -size); canvas.DrawTriangleFan(Arrow, 3); } // Draw symbols instead of + and - else if (ch == '+' || ch == '-') { int size = min(rc.right - rc.left, rc.bottom - rc.top) / 5; canvas.Rectangle((rc.left + rc.right) / 2 - size, (rc.top + rc.bottom) / 2 - size / 3, (rc.left + rc.right) / 2 + size, (rc.top + rc.bottom) / 2 + size / 3); if (ch == '+') canvas.Rectangle((rc.left + rc.right) / 2 - size / 3, (rc.top + rc.bottom) / 2 - size, (rc.left + rc.right) / 2 + size / 3, (rc.top + rc.bottom) / 2 + size); } // Draw Fly bitmap else if (caption == _T("Fly")) { Bitmap launcher1_bitmap(IDB_LAUNCHER1); canvas.ClearWhite(); if (is_down()) canvas.invert_stretch_transparent(launcher1_bitmap, COLOR_YELLOW); else canvas.stretch_transparent(launcher1_bitmap, COLOR_BLUE); } // Draw Simulator bitmap else if (caption == _T("Simulator")) { Bitmap launcher2_bitmap(IDB_LAUNCHER2); canvas.ClearWhite(); if (is_down()) canvas.invert_stretch_transparent(launcher2_bitmap, COLOR_YELLOW); else canvas.stretch_transparent(launcher2_bitmap, COLOR_BLUE); } else if (caption == _T("Green")) { InflateRect(&rc, -3, -3); canvas.DrawFilledRectangle(rc, Color(0x74, 0xFF, 0)); } else if (caption == _T("Blue")) { InflateRect(&rc, -3, -3); canvas.DrawFilledRectangle(rc, Color(0, 0x90, 0xFF)); } else if (caption == _T("Magenta")) { InflateRect(&rc, -3, -3); canvas.DrawFilledRectangle(rc, Color(0xFF, 0, 0xCB)); } else if (caption == _T("Yellow")) { InflateRect(&rc, -3, -3); canvas.DrawFilledRectangle(rc, Color(0xFF, 0xE8, 0)); } }