Пример #1
0
static void
DrawParaGlider(Canvas &canvas, const AircraftLook &look,
               const Angle angle, const RasterPoint aircraft_pos, bool inverse)
{
  RasterPoint aircraft[] = {
    // Wing
    {-16, 5},
    {-22, 4},
    {-28, 2},
    {-27, -1},
    {-26, -2},
    {-24, -3},
    {-21, -4},
    {-16, -5},
    {0, -6},
    {16, -5},
    {21, -4},
    {24, -3},
    {26, -2},
    {27, -1},
    {28, 2},
    {22, 4},
    {16, 5},

    // Arrow on wing
    {4, 6},
    {-4, 6},
    {0, -4},
   };

  PolygonRotateShift(aircraft, ARRAY_SIZE(aircraft),
                     aircraft_pos.x, aircraft_pos.y, angle, 50);

  if (inverse) {
    canvas.SelectBlackBrush();
    canvas.SelectWhitePen();
  } else {
    canvas.SelectWhiteBrush();
    canvas.SelectBlackPen();
  }

  canvas.DrawPolygon(aircraft, ARRAY_SIZE(aircraft) - 1);

  canvas.SelectNullPen();
  if (inverse)
    canvas.SelectWhiteBrush();
  else
    canvas.SelectBlackBrush();

  canvas.DrawPolygon(aircraft + ARRAY_SIZE(aircraft) - 3, 3);
}
Пример #2
0
  void Draw(Canvas &canvas, unsigned start, unsigned n) const {
#ifndef ENABLE_OPENGL
    assert(start + n <= ARRAY_SIZE(points));
#endif

    canvas.DrawPolygon(points + start, n);
  }
Пример #3
0
void
RoundRect(Canvas &canvas, int left, int top,
          int right, int bottom, unsigned radius)
{
  unsigned npoly = 0;
  RasterPoint pt[66*4];

  segment_poly(pt, left + radius, top + radius, radius,
               INT_ANGLE_RANGE * 3 / 4,
               INT_ANGLE_RANGE - 1,
               npoly);
  segment_poly(pt, right - radius, top + radius, radius,
               0, INT_ANGLE_RANGE / 4 - 1,
               npoly);
  segment_poly(pt, right - radius, bottom - radius, radius,
               INT_ANGLE_RANGE / 4,
               INT_ANGLE_RANGE / 2 - 1,
               npoly);
  segment_poly(pt, left + radius, bottom - radius, radius,
               INT_ANGLE_RANGE / 2,
               INT_ANGLE_RANGE * 3 / 4 - 1,
               npoly);

  assert(npoly < ARRAY_SIZE(pt));
  if (npoly)
    canvas.DrawPolygon(pt, npoly);
}
Пример #4
0
bool
KeyHole(Canvas &canvas, PixelScalar x, PixelScalar y, UPixelScalar radius,
        Angle start, Angle end, UPixelScalar inner_radius)
{
  // 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*2];

  segment_poly(pt, x, y, radius, istart, iend, npoly);
  segment_poly(pt, x, y, inner_radius, iend, istart, npoly);

  assert(npoly <= 66*2);
  if (npoly)
    canvas.DrawPolygon(pt, npoly);

  return true;
}
Пример #5
0
/**
 * Paints an arrow into the direction of the current task leg
 * @param canvas The canvas to paint on
 */
void
FlarmTrafficControl::PaintTaskDirection(Canvas &canvas) const
{
  if (negative(task_direction.Degrees()))
    return;

  canvas.Select(look.radar_pen);
  canvas.SelectHollowBrush();

  RasterPoint triangle[4];
  triangle[0].x = 0;
  triangle[0].y = -radius / Layout::FastScale(1) + 15;
  triangle[1].x = 7;
  triangle[1].y = triangle[0].y + 30;
  triangle[2].x = -triangle[1].x;
  triangle[2].y = triangle[1].y;
  triangle[3].x = triangle[0].x;
  triangle[3].y = triangle[0].y;

  PolygonRotateShift(triangle, 4, radar_mid,
                     task_direction - (enable_north_up ?
                                       Angle::Zero() : heading));

  // Draw the arrow
  canvas.DrawPolygon(triangle, 4);
}
Пример #6
0
void
TrailRenderer::DrawPreparedPolygon(Canvas &canvas, unsigned n)
{
  assert(points.size() >= n);

  canvas.DrawPolygon(points.begin(), n);
}
Пример #7
0
static void
DrawHangGlider(Canvas &canvas, const AircraftLook &look,
               const Angle angle, const RasterPoint aircraft_pos, bool inverse)
{
  RasterPoint aircraft[] = {
    {1, -3},
    {7, 0},
    {13, 4},
    {13, 6},
    {6, 3},
    {1, 2},
    {-1, 2},
    {-6, 3},
    {-13, 6},
    {-13, 4},
    {-7, 0},
    {-1, -3},
   };

  PolygonRotateShift(aircraft, ARRAY_SIZE(aircraft),
                     aircraft_pos.x, aircraft_pos.y, angle);

  if (inverse) {
    canvas.SelectBlackBrush();
    canvas.SelectWhitePen();
  } else {
    canvas.SelectWhiteBrush();
    canvas.SelectBlackPen();
  }

  canvas.DrawPolygon(aircraft, ARRAY_SIZE(aircraft));
}
Пример #8
0
void
TrafficRenderer::Draw(Canvas &canvas, const TrafficLook &traffic_look,
                      const FlarmTraffic &traffic, const Angle angle,
                      const FlarmColor color, const RasterPoint pt)
{
    // Create point array that will form that arrow polygon
    RasterPoint arrow[] = {
        { -4, 6 },
        { 0, -8 },
        { 4, 6 },
        { 0, 3 },
        { -4, 6 },
    };

    // Select brush depending on AlarmLevel
    switch (traffic.alarm_level) {
    case FlarmTraffic::AlarmType::LOW:
    case FlarmTraffic::AlarmType::INFO_ALERT:
        canvas.Select(traffic_look.warning_brush);
        break;
    case FlarmTraffic::AlarmType::IMPORTANT:
    case FlarmTraffic::AlarmType::URGENT:
        canvas.Select(traffic_look.alarm_brush);
        break;
    case FlarmTraffic::AlarmType::NONE:
        canvas.Select(traffic_look.safe_brush);
        break;
    }

    // Select black pen
    canvas.SelectBlackPen();

    // Rotate and shift the arrow to the right position and angle
    PolygonRotateShift(arrow, ARRAY_SIZE(arrow), pt, angle);

    // Draw the arrow
    canvas.DrawPolygon(arrow, ARRAY_SIZE(arrow));

    switch (color) {
    case FlarmColor::GREEN:
        canvas.Select(traffic_look.team_pen_green);
        break;
    case FlarmColor::BLUE:
        canvas.Select(traffic_look.team_pen_blue);
        break;
    case FlarmColor::YELLOW:
        canvas.Select(traffic_look.team_pen_yellow);
        break;
    case FlarmColor::MAGENTA:
        canvas.Select(traffic_look.team_pen_magenta);
        break;
    default:
        return;
    }

    canvas.SelectHollowBrush();
    canvas.DrawCircle(pt.x, pt.y, Layout::FastScale(11));
}
Пример #9
0
void
NextArrowRenderer::DrawArrow(Canvas &canvas, const PixelRect &rc,
                             Angle angle)
{
  /*
   * Define arrow geometry for forward pointing arrow.
   * These are the coordinates of the corners, relative to the center (o)
   *
   *                               +   (0,-head_len)
   *                              / \
   *                             /   \
   *                            /     \
   * (-head_width,-head_base)  +-+   +-+  (head_width,-head_base)
   *   (-tail_width,-head_base)  | o |  (tail_width,-head_base)
   *                             |   |
   *                             |   |
   *     (-tail_width,tail_len)  +---+  (tail_width,tail_len)
   *
   * The "tail" of the arrow is slightly shorter than the "head" to avoid
   * the corners of the tail to stick out of the bounding PixelRect.
   */
  static constexpr auto head_len = 50;
  static constexpr auto head_width = 36;
  static constexpr auto head_base = head_len - head_width;
  static constexpr auto tail_width = 16;
  static constexpr auto tail_len = head_len - tail_width / 2;

  // An array of the arrow corner coordinates.
  RasterPoint arrow[] = {
    { 0, -head_len },
    { head_width, -head_base },
    { tail_width, -head_base },
    { tail_width, tail_len },
    { -tail_width, tail_len },
    { -tail_width, -head_base },
    { -head_width, -head_base },
  };

  /*
   * Rotate the arrow, center it in the bounding rectangle, and scale
   * it to fill the rectangle.
   *
   * Note that PolygonRotateShift scales a polygon with coordinates
   * in the range -50 to +50 to fill a square with the size of the 'scale'
   * argument.
   */
  const auto size = std::min(rc.right - rc.left, rc.bottom - rc.top);
  PolygonRotateShift(arrow, ARRAY_SIZE(arrow),
                     rc.GetCenter(), angle,
                     size, false);

  // Draw the arrow.
  canvas.Select(look.arrow_pen);
  canvas.Select(look.arrow_brush);
  canvas.DrawPolygon(arrow, ARRAY_SIZE(arrow));
}
Пример #10
0
void
TerrainXSRenderer::DrawPolygon(Canvas &canvas, RasterBuffer::TerrainType type,
                               const RasterPoint *points,
                               unsigned num_points) const
{
  assert(type != RasterBuffer::TerrainType::UNKNOWN);

  canvas.Select(type == RasterBuffer::TerrainType::WATER ?
                look.sea_brush : look.terrain_brush);
  canvas.DrawPolygon(points, num_points);
}
Пример #11
0
  void FinishPolygon(Canvas &canvas) {
    if (mode != SOLID) {
      canvas.SelectNullPen();
      canvas.Select(*brush);
      mode = SOLID;
    }

    canvas.DrawPolygon(points.begin(), num_points);

    num_points = 0;
  }
Пример #12
0
void
CompassRenderer::Draw(Canvas &canvas, const Angle screen_angle,
                      const RasterPoint pos)
{
  RasterPoint arrow[5] = { { 0, -13 }, { -6, 10 }, { 0, 4 }, { 6, 10 }, { 0, -13 } };

  canvas.Select(look.compass_pen);
  canvas.Select(look.compass_brush);

  // North arrow
  PolygonRotateShift(arrow, ARRAY_SIZE(arrow), pos.x, pos.y, -screen_angle);
  canvas.DrawPolygon(arrow, ARRAY_SIZE(arrow));

  canvas.Select(look.compass_triangle_pen);
  canvas.Select(look.compass_triangle_brush);

  RasterPoint black_triangle[4] = { { 0, -13 }, { 6, 10}, { 0, 4}, { 0, -13 } };
  PolygonRotateShift(black_triangle, ARRAY_SIZE(black_triangle),
                     pos.x, pos.y, -screen_angle);
  canvas.DrawPolygon(black_triangle, ARRAY_SIZE(black_triangle));
}
Пример #13
0
void
CheckBoxControl::OnPaint(Canvas &canvas)
{
  const auto &cb_look = look->check_box;

  const bool focused = HasCursorKeys() && HasFocus();

  if (focused)
    canvas.Clear(cb_look.focus_background_brush);
  else if (HaveClipping())
    canvas.Clear(look->background_brush);

  const auto &state_look = IsEnabled()
    ? (pressed
       ? cb_look.pressed
       : (focused
          ? cb_look.focused
          : cb_look.standard))
    : cb_look.disabled;

  unsigned size = canvas.GetHeight() - 4;

  canvas.Select(state_look.box_brush);
  canvas.Select(state_look.box_pen);
  canvas.Rectangle(2, 2, size, size);

  if (checked) {
    canvas.Select(state_look.check_brush);
    canvas.SelectNullPen();

    BulkPixelPoint check_mark[] = {
      {-8, -2},
      {-3, 6},
      {7, -9},
      {8, -5},
      {-3, 9},
      {-9, 2},
    };

    unsigned top = canvas.GetHeight() / 2;
    for (unsigned i = 0; i < ARRAY_SIZE(check_mark); ++i) {
      check_mark[i].x = (check_mark[i].x * (int)size) / 24 + top;
      check_mark[i].y = (check_mark[i].y * (int)size) / 24 + top;
    }

    canvas.DrawPolygon(check_mark, ARRAY_SIZE(check_mark));
  }

  canvas.Select(*cb_look.font);
  canvas.SetTextColor(state_look.text_color);
  canvas.SetBackgroundTransparent();
  canvas.DrawText(canvas.GetHeight() + 2, 2, caption.c_str());
}
Пример #14
0
static void
DrawShape(Canvas &canvas, AbstractAirspace::Shape shape, const RasterPoint pt,
          unsigned radius, const std::vector<RasterPoint> &pts)
{
  if (shape == AbstractAirspace::Shape::CIRCLE)
    canvas.DrawCircle(pt.x, pt.y, radius);
  else if (IsAncientHardware())
    canvas.Rectangle(pt.x - radius, pt.y - radius,
                     pt.x + radius, pt.y + radius);
  else
    canvas.DrawPolygon(&pts[0], (unsigned)pts.size());
}
Пример #15
0
static void
DrawMirroredPolygon(const RasterPoint *src, RasterPoint *dst, unsigned points,
                    Canvas &canvas, const Angle angle,
                    const RasterPoint pos)
{
  std::copy(src, src + points, dst);
  for (unsigned i = 0; i < points; ++i) {
    dst[2 * points - i - 1].x = -dst[i].x;
    dst[2 * points - i - 1].y = dst[i].y;
  }
  PolygonRotateShift(dst, 2 * points, pos.x, pos.y, angle, 50);
  canvas.DrawPolygon(dst, 2 * points);
}
void
ThermalAssistantWindow::PaintPoints(Canvas &canvas) const
{
#ifdef ENABLE_OPENGL
  GLBlend blend(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
#elif defined(USE_GDI)
  canvas.SetMixMask();
#endif /* GDI */

  canvas.Select(look.polygon_brush);
  canvas.Select(look.polygon_pen);
  canvas.DrawPolygon(lift_points, 36);
}
Пример #17
0
void
BestCruiseArrowRenderer::Draw(Canvas &canvas, const TaskLook &look,
                              const Angle screen_angle,
                              const Angle best_cruise_angle,
                              const RasterPoint pos)
{
  canvas.Select(look.best_cruise_track_pen);
  canvas.Select(look.best_cruise_track_brush);

  RasterPoint arrow[] = { { -1, -40 }, { -1, -62 }, { -6, -62 }, {  0, -70 },
                          {  6, -62 }, {  1, -62 }, {  1, -40 }, { -1, -40 } };

  PolygonRotateShift(arrow, ARRAY_SIZE(arrow), pos,
                     best_cruise_angle - screen_angle);
  canvas.DrawPolygon(arrow, ARRAY_SIZE(arrow));
}
Пример #18
0
void
RoundRect(Canvas &canvas, int left, int top,
          int right, int bottom, unsigned radius)
{
  unsigned npoly = 0;
  RasterPoint pt[66*4];

  segment_poly(pt, left + radius, top + radius, radius, 3072, 4095, npoly);
  segment_poly(pt, right - radius, top + radius, radius, 0, 1023, npoly);
  segment_poly(pt, right - radius, bottom - radius, radius, 1024, 2047, npoly);
  segment_poly(pt, left + radius, bottom - radius, radius, 2048, 3071, npoly);

  assert(npoly < ARRAY_SIZE(pt));
  if (npoly)
    canvas.DrawPolygon(pt, npoly);
}
Пример #19
0
void
RoundRect(Canvas &canvas, PixelScalar left, PixelScalar top,
          PixelScalar right, PixelScalar bottom, UPixelScalar radius)
{
  int npoly = 0;
  RasterPoint pt[66*4];

  segment_poly(pt, left + radius, top + radius, radius, 3072, 4095, npoly);
  segment_poly(pt, right - radius, top + radius, radius, 0, 1023, npoly);
  segment_poly(pt, right - radius, bottom - radius, radius, 1024, 2047, npoly);
  segment_poly(pt, left + radius, bottom - radius, radius, 2048, 3071, npoly);

  assert(npoly <= 66*4);
  if (npoly)
    canvas.DrawPolygon(pt, npoly);
}
Пример #20
0
static void
Draw(Canvas &canvas)
{
  PixelRect rc = canvas.GetRect();
  rc.Grow(-0.2 * rc.GetSize().cx);
  
  /* draw the banner text with a large font */
  Font small_font;
  small_font.LoadFile("/opt/LK8000/share/fonts/DejaVuSansCondensed.ttf", (rc.GetSize().cy / 25));
  canvas.Select(small_font);
  canvas.SetTextColor(COLOR_BLACK);
  canvas.SetBackgroundTransparent();

  const TCHAR *const text = _T("Powered Off");
  const PixelSize text_size = canvas.CalcTextSize(text);
  const RasterPoint text_pos = {
      rc.left + 16,
      rc.bottom - 16 - text_size.cy
  };
  canvas.DrawText(text_pos.x, text_pos.y, text);
  
  Font big_font;
  big_font.LoadFile("/opt/LK8000/share/fonts/DejaVuSansCondensed-Bold.ttf", (rc.GetSize().cy / 10));
  canvas.Select(big_font);
  
  const TCHAR *const text2 = _T("LK8000");
  const PixelSize text2_size = canvas.CalcTextSize(text2);
  const RasterPoint text2_pos = {
      (rc.left + rc.GetSize().cx + text2_size.cx) / 2,
      (rc.top + (rc.GetSize().cy / 10))
  };
  canvas.DrawText(text2_pos.x, text2_pos.y, text2);
  
  const double Scale = (double)rc.GetSize().cx / (double)bird_size.cx;
  
  RasterPoint polygon[array_size(bird_polygon)] = {};
  std::transform(std::begin(bird_polygon), std::end(bird_polygon), std::begin(polygon), [Scale, rc, text2_size, text2_pos]( const RasterPoint& pt ) {
      return RasterPoint(pt.x*Scale + rc.left, pt.y*Scale + text2_pos.y + text2_size.cy);
  });
  
  canvas.SelectBlackBrush();
  canvas.DrawPolygon(polygon, array_size(polygon));
}
Пример #21
0
void
RenderFAISector(Canvas &canvas, const WindowProjection &projection,
                const GeoPoint &pt1, const GeoPoint &pt2,
                bool reverse, const FAITriangleSettings &settings)
{
  GeoPoint geo_points[FAI_TRIANGLE_SECTOR_MAX];
  GeoPoint *geo_end = GenerateFAITriangleArea(geo_points, pt1, pt2,
                                              reverse, settings);

  GeoPoint clipped[FAI_TRIANGLE_SECTOR_MAX * 3],
    *clipped_end = clipped +
    GeoClip(projection.GetScreenBounds().Scale(fixed(1.1)))
    .ClipPolygon(clipped, geo_points, geo_end - geo_points);

  RasterPoint points[FAI_TRIANGLE_SECTOR_MAX], *p = points;
  for (GeoPoint *geo_i = clipped; geo_i != clipped_end;)
    *p++ = projection.GeoToScreen(*geo_i++);

  canvas.DrawPolygon(points, p - points);
}
Пример #22
0
static void
DrawMirroredPolygon(const RasterPoint *src, unsigned points,
                    Canvas &canvas, const Angle angle,
                    const RasterPoint pos)
{
  RasterPoint dst[64];
  assert(2 * points <= ARRAY_SIZE(dst));

  std::copy(src, src + points, dst);
  for (unsigned i = 0; i < points; ++i) {
    dst[2 * points - i - 1].x = -dst[i].x;
    dst[2 * points - i - 1].y = dst[i].y;
  }
#ifdef ENABLE_OPENGL
  CanvasRotateShift rotate_shift(pos, angle, 50);
#else
  PolygonRotateShift(dst, 2 * points, pos.x, pos.y, angle, 50);
#endif
  canvas.DrawPolygon(dst, 2 * points);
}
Пример #23
0
static void
DrawMirroredPolygon(const BulkPixelPoint *src, unsigned points,
                    Canvas &canvas, const Angle angle,
                    const PixelPoint pos)
{
  BulkPixelPoint dst[64];
  assert(2 * points <= ARRAY_SIZE(dst));

  std::copy_n(src, points, dst);
  for (unsigned i = 0; i < points; ++i) {
    dst[2 * points - i - 1].x = -dst[i].x;
    dst[2 * points - i - 1].y = dst[i].y;
  }
#ifdef ENABLE_OPENGL
  PolygonRotateShift(dst, 2 * points, pos, angle, 70);
#else
  PolygonRotateShift(dst, 2 * points, pos, angle, 50);
#endif
  canvas.DrawPolygon(dst, 2 * points);
}
Пример #24
0
bool
KeyHole(Canvas &canvas, int x, int y, unsigned radius,
        Angle start, Angle end, unsigned inner_radius)
{
  // 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[66*2];

  segment_poly(pt, x, y, radius, istart, iend, npoly);
  segment_poly(pt, x, y, inner_radius, iend, istart, npoly);

  assert(npoly < ARRAY_SIZE(pt));
  if (npoly)
    canvas.DrawPolygon(pt, npoly);

  return true;
}
Пример #25
0
bool
Annulus(Canvas &canvas, PixelPoint center, unsigned radius,
        Angle start, Angle end, unsigned inner_radius)
{
  // dont draw if out of view
  if (!IsCircleVisible(canvas, center, radius))
    return false;

  const int istart = NATIVE_TO_INT(start.Native());
  const int iend = NATIVE_TO_INT(end.Native());

  unsigned npoly = 0;
  BulkPixelPoint pt[66*2];

  segment_poly(pt, center, radius, istart, iend, npoly);
  segment_poly(pt, center, inner_radius, iend, istart, npoly, false);

  assert(npoly <= ARRAY_SIZE(pt));
  if (npoly)
    canvas.DrawPolygon(pt, npoly);

  return true;
}
Пример #26
0
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]);
  }
}
Пример #27
0
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]);
  }
}
Пример #28
0
//------------------------------------------------------------------------------
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();
    }
  }
Пример #29
0
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);

}
Пример #30
0
void
VarioBarRenderer::Draw(Canvas &canvas, const PixelRect &rc,
                            const MoreData &basic,
                            const DerivedInfo &calculated,
                            const GlidePolar &glide_polar,
                            const bool vario_bar_avg_enabled) const
{
#ifdef ENABLE_OPENGL
  const ScopeAlphaBlend alpha_blend;
#endif

  RasterPoint VarioBar[6] = {
      { 0, 0 }, { 9, -9 }, { 18, 0 }, { 18, 0 }, { 9, 0 }, { 0, 0 }
  };
  RasterPoint VarioBarAvg[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_arrow_av[4] = {
      { 0, 0 }, { 9, 9 }, { 9, 15 }, { 0, 6 }
  };
  RasterPoint mc_arrow[6] = {
      { 0, 0 }, { 9, -9 }, { 18, 0 }, { 18, -2 }, { 9, -11 }, { 0, -2 }
  };

  TCHAR Value[10];

  const int y0 = (rc.bottom + rc.top) / 2;

  /* NOTE: size_divisor replaces the fixed value 9 that was used throughout
   * the code sink 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 auto size_divisor =
    std::max((fixed) Layout::Scale(70 / (rc.bottom - rc.top)), fixed(0.15));

  PixelScalar dy_variobar = 0;
  PixelScalar dy_variobar_av = 0;
  PixelScalar dy_variobar_mc = 0;

  PixelScalar clipping_arrow_offset = Layout::Scale(4);
  PixelScalar clipping_arrow_av_offset = Layout::Scale(4);
//  PixelScalar clipping_arrow_mc_offset = Layout::Scale(4);

  auto vario_gross = basic.brutto_vario;

  FormatUserVerticalSpeed(vario_gross, Value, false, true);
  canvas.Select(*look.font);
  const PixelSize text_size = canvas.CalcTextSize(Value);

  auto vario_avg = calculated.average;

  // cut vario_gross at +- 5 meters/s
  if (vario_gross > fixed(5))
    vario_gross = fixed(5);
  if (vario_gross < fixed(-5))
    vario_gross = fixed(-5);

  int Offset = (int)(vario_gross / size_divisor);

  Offset = Layout::Scale(Offset);
  if (!positive(vario_gross)) {
    VarioBar[1].y = Layout::Scale(9);
    dy_variobar = text_size.cy + 2;
  } else {
    VarioBar[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_variobar = -1;
  }

  // cut vario_avg at +- 5 meters/s
  if (vario_avg > fixed(5))
    vario_avg = fixed(5);
  if (vario_avg < fixed(-5))
    vario_avg = fixed(-5);

  int OffsetAvg = int(vario_avg / size_divisor);

  OffsetAvg = Layout::Scale(OffsetAvg);
  if (!positive(vario_avg)) {
    VarioBarAvg[1].y = Layout::Scale(9);
    dy_variobar_av = text_size.cy + 2;
  } else {
    VarioBarAvg[1].y = -Layout::Scale(9);
    clipping_arrow_av[1].y = -clipping_arrow_av[1].y;
    clipping_arrow_av[2].y = -clipping_arrow_av[2].y;
    clipping_arrow_av[3].y = -clipping_arrow_av[3].y;
    clipping_arrow_av_offset = -clipping_arrow_av_offset;
    dy_variobar_av = -1;
  }


  //clip MC Value
  auto mc_val = glide_polar.GetMC();
  if (mc_val > fixed(5))
    mc_val = fixed(5);
  if (!positive(mc_val)) {
    dy_variobar_mc = text_size.cy + 2;
  }else{
    dy_variobar_mc = -1;
  }

  int OffsetMC = int(mc_val / size_divisor);
  OffsetMC = Layout::Scale(OffsetMC);

  for (unsigned i = 0; i < 6; i++) {
    VarioBar[i].y += y0 + dy_variobar;
    VarioBar[i].x = rc.right - Layout::Scale(VarioBar[i].x);
  }

  VarioBar[0].y -= Offset;
  VarioBar[1].y -= Offset;
  VarioBar[2].y -= Offset;

  for (unsigned i = 0; i < 4; i++) {
    VarioBarAvg[i].y += y0 + dy_variobar_av;
    VarioBarAvg[i].x = rc.right-Layout::Scale(VarioBarAvg[i].x);
  }

  VarioBarAvg[0].y -= OffsetAvg;
  VarioBarAvg[1].y -= OffsetAvg;

  // prepare mc arrow
  for (unsigned i = 0; i < 6; i++) {
    mc_arrow[i].y = Layout::Scale(mc_arrow[i].y) + y0
      - OffsetMC + dy_variobar_mc;
    mc_arrow[i].x = rc.right - Layout::Scale(mc_arrow[i].x);
  }

  // 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_variobar;
    clipping_arrow[i].x = rc.right - Layout::Scale(clipping_arrow[i].x);
  }

  // prepare clipping avg
  for (unsigned i = 0; i < 4; i++) {
    clipping_arrow_av[i].y = Layout::Scale(clipping_arrow_av[i].y) + y0 - OffsetAvg
      + clipping_arrow_av_offset + dy_variobar_av;
    clipping_arrow_av[i].x = rc.right-Layout::Scale(clipping_arrow_av[i].x);
  }

  // draw actual vario bar
  if (!positive(vario_gross)) {
    canvas.Select(look.pen_sink);
    canvas.Select(look.brush_sink);
  } else {
    canvas.Select(look.pen_climb);
    canvas.Select(look.brush_climb);
  }

  canvas.DrawPolygon(VarioBar, 6);

  // draw clipping arrow
  if (vario_gross <= fixed(-5) || vario_gross >= fixed(5))
    canvas.DrawPolygon(clipping_arrow, 6);

  // draw avg vario bar
  if (!positive(vario_avg) && vario_bar_avg_enabled) {
      canvas.Select(look.pen_sink);
      canvas.Select(look.brush_sink_avg);
  } else {
    canvas.Select(look.pen_climb);
    canvas.Select(look.brush_climb_avg);
  }

  canvas.DrawPolygon(VarioBarAvg, 4);

  if (vario_avg <= fixed(-5.0) || vario_avg >= fixed(5.0))
      canvas.DrawPolygon(clipping_arrow_av, 4);

  //draw MC arrow
  canvas.Select(look.pen_mc);
  canvas.Select(look.brush_mc);

  canvas.DrawPolygon(mc_arrow, 6);

  //draw text
  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, rc.right, y0, style, rc);
  } else
    TextInBox(canvas, Value, rc.right-Layout::Scale(18), y0, style, rc);
}