/// <summary>
        /// Called whenever the underlying frame changes to redraw the frame.
        /// </summary>
        public void DrawFrame(PlayFrame frame, 
                          Graphics display, 
                          PitchScreenCoordConverter converter,
                          VisualOverlay overlay,
                          Rectangle displayRectangle)
        {
            BufferedGraphicsContext currentContext;
              BufferedGraphics myBuffer;
              currentContext = BufferedGraphicsManager.Current;
              myBuffer = currentContext.Allocate(display,
                                         displayRectangle);
              myBuffer.Graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
              myBuffer.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
              myBuffer.Graphics.Clear(mBackColor);

              // Draw the pitch itself.
              DrawPitch(myBuffer.Graphics, converter);

              // This moves items around based on what the user is doing.
              // e.g. If a user is dragging a cut at the moment it adds a new cut for
              // the given player.
              PlayFrame adjustableFrame = FrameRenderer.AdjustFrameForOverlay(frame,
                                                                      overlay,
                                                                      converter);

              foreach (Player player in adjustableFrame.PlayerMovement.Keys)
              {
            List<LinearMovement> playerMoves = adjustableFrame.PlayerMovement[player];

            if (playerMoves.Count > 0)
            {

              DrawPlayer(player,
                     playerMoves[0].FinalPosition,
                     myBuffer.Graphics,
                     converter,
                     false);

              if (playerMoves.Count > 1)
              {
            List<Point> cutLocations = new List<Point>();

            foreach (LinearMovement playerMove in playerMoves)
            {
              cutLocations.Add(converter.pitchToScreenCoords(playerMove.FinalPosition));
            }

            myBuffer.Graphics.DrawLines(mCutPen, cutLocations.ToArray<Point>());
              }
            }
              }

              foreach (Trigger trigger in adjustableFrame.Triggers)
              {
            DrawTrigger(myBuffer.Graphics, trigger, converter);
              }

              // Draw the disc after the players because the sprite sits on top of the
              // player sprite who is holding it.
              if (adjustableFrame.DiscFrameMovement.Thrower != null)
              {
            DrawDisc(myBuffer.Graphics,
                 adjustableFrame.DiscFrameMovement.StartPosition(),
                 converter);

            if (adjustableFrame.DiscFrameMovement.HasMoved)
            {
              DrawDiscFlight(myBuffer.Graphics,
                         adjustableFrame.DiscFrameMovement.StartPosition(),
                         adjustableFrame.DiscFrameMovement.ControlPoint,
                         adjustableFrame.DiscFrameMovement.EndPosition(),
                         converter);
            }
              }
              else if (overlay.PlacingDisc)
              {
            // The mouse location is stored in the overlay but we need to pass the
            // pitch coordinates to the drawing function.
            DrawDisc(myBuffer.Graphics,
                 converter.screenToPitchCoords(overlay.MouseLocation),
                 converter);
              }

              myBuffer.Render();
              myBuffer.Dispose();
        }
        /// <summary>
        /// Render a small square for a player. This is used when we're rendering
        /// into a small space.
        /// </summary>
        /// <param name="graphics"></param>
        /// <param name="player"></param>
        /// <param name="location"></param>
        /// <param name="converter"></param>
        private void DrawSmallPlayer(Graphics graphics, 
                                 Player player, 
                                 PointF location, 
                                 PitchScreenCoordConverter converter)
        {
            Point screenCoords = converter.pitchToScreenCoords(location);
              Brush playerBrush = player.PlayerTeam.UniqueId ==
                          Team.RED_TEAM.UniqueId ? Brushes.Red : Brushes.Blue;

              graphics.FillRectangle(playerBrush,
                             screenCoords.X,
                             screenCoords.Y,
                             4, 4);
        }
        /// <summary>
        /// Draw the disc flight.
        /// 
        /// Currently simply a straight line from A to B. Could enhance this so
        /// that it draws a cardinal spline instead at some point. The UI to draw
        /// that is the more difficult area.
        /// </summary>
        /// <param name="display"></param>
        /// <param name="startLocation"></param>
        /// <param name="controlPoint"></param>
        /// <param name="endLocation"></param>
        /// <param name="converter"></param>
        private void DrawDiscFlight(Graphics display,
                                PointF startLocation,
                                PointF controlPoint,
                                PointF endLocation,
                                PitchScreenCoordConverter converter)
        {
            Point screenCoordsStart = converter.pitchToScreenCoords(startLocation);
              Point screenCoordsEnd = converter.pitchToScreenCoords(endLocation);
              Point screenControlPoint = converter.pitchToScreenCoords(controlPoint);

              QuadraticBezierCurve curve = new QuadraticBezierCurve(screenCoordsStart,
                                                            screenControlPoint,
                                                            screenCoordsEnd);

              display.DrawBeziers(mDiscFlightPen, curve.ToCubic());

              display.DrawRectangle(mDiscFlightPen,
                            screenControlPoint.X - 1,
                            screenControlPoint.Y - 1,
                            2, 2);
        }
        /// <summary>
        /// Draw a string onto the pitch at the given pitch coordinates. Does
        /// the conversion from pitch to screen internally.
        /// </summary>
        /// <param name="display"></param>
        /// <param name="converter"></param>
        /// <param name="text"></param>
        /// <param name="position"></param>
        /// <param name="font"></param>
        /// <param name="brush"></param>
        public void DrawString(Graphics display,
                           PitchScreenCoordConverter converter,
                           String text,
                           PointF position,
                           Font font,
                           Brush brush)
        {
            Point screenCoords = converter.pitchToScreenCoords(position);

              display.DrawString(text, font, brush, screenCoords);
        }
        /// <summary>
        /// Draw a single sprite on the pitch at the given coordinates. Does the 
        /// conversion of pitch -> screen internally.
        /// </summary>
        /// <param name="display">The display on which to draw.</param>
        /// <param name="converter">The converter utility used to turn pitch
        /// coordinates into screen coordinates</param>
        /// <param name="image">The image to draw</param>
        /// <param name="position">The pitch coordinates</param>
        /// <param name="width">Pitch width</param>
        /// <param name="length">Pitch height/length</param>
        public void DrawSprite(Graphics display,
                           PitchScreenCoordConverter converter, 
                           Image image, 
                           PointF position, 
                           float width, 
                           float length)
        {
            Rectangle imagePlacement = new Rectangle();
              Point screenCoords = converter.pitchToScreenCoords(position);
              PointF imageSize = new PointF(width, length);
              Point convertedImageSize = converter.pitchToScreenSize(imageSize);

              imagePlacement.Location = screenCoords;
              imagePlacement.Width = convertedImageSize.X;
              imagePlacement.Height = convertedImageSize.Y;

              display.DrawImage(image,
                        imagePlacement);
        }
        /// <summary>
        /// The pitch is drawn as a pair of rectangles rather than as a sprite.
        /// 
        /// All conversion between pitch coordinates and screen coordinates is done
        /// internally.
        /// </summary>
        /// <param name="display"></param>
        /// <param name="converter"></param>
        public void DrawPitch(Graphics display, 
                          PitchScreenCoordConverter converter)
        {
            Rectangle outerPitch = new Rectangle();
              Rectangle innerPitch = new Rectangle();
              using (Pen linePen = new Pen(mLineColor, mLineWidth))
              {
            Point bottomRight = converter.pitchToScreenCoords(
              new PointF(sPitchWidth, sPitchLength));
            Point innerBottomRight = converter.pitchToScreenCoords(
              new PointF(sPitchWidth, (sPitchLength - 2.0f * sEndzoneDepth)));
            Point leftBrick = converter.pitchToScreenCoords(
              new PointF(sPitchWidth / 2.0f,
                     sEndzoneDepth + sBrickDistance));
            Point rightBrick = converter.pitchToScreenCoords(
              new PointF(sPitchWidth / 2.0f,
                     sPitchLength - sEndzoneDepth - sBrickDistance));
            int brickDistanceScreen = converter.pitchToScreenLength(sBrickRadius);

            outerPitch.Location = converter.pitchToScreenCoords(new PointF(0.0f, 0.0f));
            outerPitch.Width = bottomRight.X;
            outerPitch.Height = bottomRight.Y;

            innerPitch.Location = converter.pitchToScreenCoords(new PointF(0.0f, sEndzoneDepth));
            innerPitch.Width = innerBottomRight.X;
            innerPitch.Height = innerBottomRight.Y;

            display.FillRectangle(mPitchBrush, outerPitch);
            display.DrawRectangle(linePen, outerPitch);
            display.DrawRectangle(linePen, innerPitch);
            DrawCross(display, linePen, leftBrick, brickDistanceScreen);
            DrawCross(display, linePen, rightBrick, brickDistanceScreen);
              }
        }