/// <summary>
        ///     Positions the arrow of the contest candidates
        /// </summary>
        /// <param name="contest">The contest.</param>
        /// <externalUnit cref="Candidate"/>
        /// <externalUnit cref="Contest"/>
        /// <externalUnit cref="PointF"/>
        /// <externalUnit cref="RectangleF"/>
        /// <externalUnit cref="TargetLayout"/>
        /// <revision revisor="dev11" date="3/10/2009" version="1.0.8.2101">
        ///     Member Created
        /// </revision>
        /// <revision revisor="dev11" date="03/23/2009" version="1.0.9.0701">
        ///     added support for oval target
        /// </revision>
        protected override void PositionCandidates(Contest contest)
        {
            PointF     point;
            RectangleF bounds;

            foreach (Candidate candidate in contest.Candidates)
            {
                bounds = candidate.Bounds;
                point  = new PointF();
                switch (target.Type)
                {
                case TargetType.Oval:
                    point.X = bounds.X +
                              (bounds.Width
                               -
                               PointsPerInchF
                               * target.GetFltParam(TargetParam.Width)) /
                              2f;
                    point.Y = bounds.Bottom - CellPadding
                              -
                              PointsPerInchF
                              * target.GetFltParam(TargetParam.Height);
                    break;

                default:
                    // the arrow is positioned horizontally centered,
                    // vertically aligned to the bottom of the cell
                    point.X = bounds.X
                              + (bounds.Width - this.arrowGapWidth
                                 -
                                 Convert.ToSingle(
                                     PointsPerInchD * ArrTailX[3]))
                              / 2f;

                    // y (top of arrow) = [cell bottom] - [cell padding] -
                    // [arrow height]
                    point.Y = bounds.Bottom - CellPadding -
                              Convert.ToSingle(PointsPerInchF * ArrHeadY[6]);
                    break;
                }

                candidate.XYArrow = point;
            }
        }
        /// <summary>
        ///     Positions the texts of a contest using a supplied coordinates
        ///     for the top left corner of the contest header.
        /// </summary>
        /// <param name="contest">The contest.</param>
        /// <param name="x">
        ///     The left side of the contest header (in points)
        /// </param>
        /// <param name="y">
        ///     The top side of the contest header (in points)
        /// </param>
        /// <externalUnit cref="OfficeText"/>
        /// <externalUnit cref="PDFxFont"/>
        /// <externalUnit cref="PointF"/>
        /// <externalUnit cref="RectangleF"/>
        /// <revision revisor="dev11" date="3/10/2009" version="1.0.">
        ///     Member Created
        /// </revision>
        protected override void PositionTexts(Contest contest, float x, float y)
        {
            List <OfficeText> texts = contest.Texts;

            float curY = y + CellPadding,
                  cx   = x + ColWidthContest / 2f;

            for (int i = 0; i < texts.Count; i = i + 1)
            {
                OfficeText text = texts[i];
                PDFxFont   font = GetFont(text.Font);
                double     yMax = font.getYMax(text.FontSize),
                           yMin = font.getYMin(text.FontSize); // negative value

                PointF point = new PointF();
                point.X     = cx;                            // relative to the page
                point.Y     = Convert.ToSingle(curY + yMax); // relative to the page
                text.XYText = point;

                curY = curY + Convert.ToSingle(yMax - yMin);
            }
        }
        /// <summary>
        ///     Loads the contest from an XML node, including all
        ///     candidate subnodes.
        /// </summary>
        /// <param name="xmlCont">The XML cont.</param>
        /// <param name="defFont">The def font.</param>
        /// <param name="defSize">Size of the def.</param>
        /// <returns>
        ///     A <see cref="Contest" /> object from the xml.
        /// </returns>
        /// <externalUnit cref="Contest"/>
        /// <externalUnit cref="Keys"/>
        /// <externalUnit cref="XmlNode"/>
        /// <revision revisor="dev11" date="12/23/2008" version="1.0.0.0">
        ///     Member Created
        /// </revision>
        public static Contest LoadFromXml(
            XmlNode xmlCont, string defFont, double defSize)
        {
            // read information from the attributes
            string name = xmlCont.Attributes[Keys.ATR_CST_NAME].Value;

            int id = int.Parse(xmlCont.Attributes[Keys.ATR_CST_ID].Value);

            Contest contest = new Contest(id, name);

            try
            {
                XmlAttribute breakAttr = xmlCont.Attributes[Keys.ATR_CST_BREAK];
                contest.Break =
                    (BreakType)Enum.Parse(typeof(BreakType), breakAttr.Value);
            }
            catch
            {
            }

            // get the text lines
            XmlNodeList texts = xmlCont.SelectNodes(Keys.TAG_OFFICE_TXT);

            foreach (XmlNode text in texts)
            {
                contest.Texts.Add(
                    OfficeText.LoadFromXml(text, defFont, defSize));
            }

            // get the candidates
            XmlNodeList cands = xmlCont.SelectNodes(Keys.TAG_CANDIDATE);

            foreach (XmlNode cand in cands)
            {
                contest.Candidates.Add(Candidate.LoadFromXml(cand));
            }

            return(contest);
        }
        /// <summary>
        ///     Loads from db.
        /// </summary>
        /// <param name="ballots">The ballots.</param>
        /// <param name="contests">The contests (StpCont).</param>
        /// <param name="candidates">The candidates.</param>
        /// <param name="ballotId">The ballot id.</param>
        /// <param name="contId">The contest id.</param>
        /// <param name="defFont">The def font.</param>
        /// <param name="defSize">Size of the def.</param>
        /// <returns>
        ///     A <see cref="Contest" /> from the database.
        /// </returns>
        /// <externalUnit/>
        /// <revision revisor="dev11" date="12/19/2008" version="1.0.0.0">
        ///     Member Created
        /// </revision>
        /// <revision revisor="dev11" date="04/14/2009" version="1.0.11.0401">
        ///     Passing ballot style id to candidates as well since candidate
        ///     may appear more than once on the ballot entry set.
        /// </revision>
        public static Contest LoadFromDb(
            BallotEntrySet ballots,
            BallotEntrySet contests,
            BallotEntrySet candidates,
            int ballotId,
            int contId,
            string defFont,
            double defSize)
        {
            int idxBal = ballots.FindIndex(
                StpBallot.BallotStyleId,
                ballotId,
                StpBallot.ContestId,
                contId),
                idxCst = contests.FindIndex(StpCont.ContestId, contId),
                curCst,
                curCnd = ballots.GetValueInt(idxBal, StpBallot.CandDispFormat),

            // using 0x0003 since this is a 2-bit flag that can take all 4
            // values: 0, 1, 2, 3
                cstFormat = // 0x0003 &
                            ballots.GetValueInt(idxBal, StpBallot.ContDispFormat);
            var contest = new Contest(contId);

            // read break format settings
            contest.Break =
                (BreakType)Enum.ToObject(typeof(BreakType), cstFormat);

            do
            {
                // Load office texts from the contest entry set until a
                // different contest id is found. Start at the current index
                // found above.
                contest.Texts.Add(
                    OfficeText.LoadFromDb(contests, idxCst, defFont, defSize));

                // Increment the index by 1 and test if the contest id is
                // the same
                idxCst = idxCst + 1;
                if (idxCst < contests.Count)
                {
                    curCst = contests.GetValueInt(idxCst, StpCont.ContestId);
                }
                else
                {
                    // idxCst is greater than the number of elements in the
                    // collection, so simply use -1 to break the loop
                    curCst = -1;
                }
            }while (curCst == contId);

            do
            {
                // get the current candidate id
                curCnd = ballots.GetValueInt(idxBal, StpBallot.CandidateId);

                // load all candidates for this contest
                contest.Candidates.Add(
                    Candidate.LoadFromDb(
                        ballots,
                        candidates,
                        curCnd,
                        ballotId));

                // increment the index by 1 and test if the contest id is
                // the same
                idxBal = idxBal + 1;

                if (idxBal < ballots.Count)
                {
                    curCst = ballots.GetValueInt(idxBal, StpBallot.ContestId);
                }
                else
                {
                    curCst = -1;
                }
            }while (curCst == contId);

            return(contest);
        }