/// <summary>
		/// Draws single line into rectangle located at <paramref name="pnt"/> with specified width.
		/// ParagraphAlignemnt is considered here.
		/// </summary>
		/// <param name="gr"></param>
		/// <param name="pnt"></param>
		/// <param name="width"></param>
		/// <param name="i"></param>
		/// <param name="pf"></param>
		/// <param name="trimmedLine"></param>
		private void DrawSingleLineAligned(Graphics gr, PointF pnt, float width, 
			Interval i, ParagraphFormat pf, bool trimmedLine)
		{
			float lineWidth;
			switch(pf.Alignment)
			{
				case ParagraphAlignment.Left:
					if(trimmedLine)
						DrawTrimmedLine(gr, pnt, width,  i, pf);
					else
						DrawSingleLineUnaligned(gr, pnt, i);
					break;
				case ParagraphAlignment.Right:
					if(trimmedLine)
					{
						lineWidth=MeasureTrimmedLine(gr, width, i, pf).Width;
						DrawTrimmedLine(gr,new PointF(pnt.X+width-lineWidth,pnt.Y), width, i, pf);
					} 
					else 
					{
						lineWidth=Measure(gr, i, false).Width;
						DrawSingleLineUnaligned(gr,new PointF(pnt.X+width-lineWidth,pnt.Y), i);
					}
					break;
				case ParagraphAlignment.Center:
					if(trimmedLine)
					{
						lineWidth=MeasureTrimmedLine(gr, width, i, pf).Width;
						DrawTrimmedLine(gr,new PointF(pnt.X+(width-lineWidth)/2,pnt.Y), width, i, pf);
					} 
					else 
					{
						lineWidth=Measure(gr, i, false).Width;
						DrawSingleLineUnaligned(gr, new PointF(pnt.X+(width-lineWidth)/2,pnt.Y), i);
					}
					break;
				case ParagraphAlignment.Full:
					if(trimmedLine)
						DrawTrimmedLine(gr, pnt, width,  i, pf);
					else if(IsWrapedLine(i))
						DrawSingleLineFullyAligned(gr, pnt, width, i);
					else
						DrawSingleLineUnaligned(gr, pnt, i);
					break;
			}
		}
Exemple #2
0
		/// <summary>
		/// Paint the node text
		/// </summary>
		/// <param name="oNode"></param>
		/// <param name="oGraphics"></param>
		/// <param name="nX"></param>
		/// <param name="nY"></param>		
		private void PaintNodeText(Node oNode, Graphics oGraphics, int nX, int nY, 
			ref Hashtable m_mapRectToItemCheck, ref Hashtable m_mapItemCheckToRect)
		{
			int nAlpha = oNode.TreeView.GetNodeAlpha(oNode);
			Font oFont = oNode.GetFont();

			if (oNode.Flash == true)
				nAlpha = 255;

			//if (oNode.GetShowPlusMinus() == false)
			//	nX -= 15;
			
			SizeF oTextSize = oGraphics.MeasureString(oNode.GetText(), oNode.GetFont(), oNode.GetTreeView().GetDrawWidth() - nX - 8);
			if (m_oTreeView.Multiline == false)
				oTextSize = oGraphics.MeasureString(oNode.GetText(), oFont);

			oNode.Top = nY + (int)oTextSize.Height + 2;

			int nTextWidth = (int)oTextSize.Width;
			oNode.TextWidth = nTextWidth;

			if (oTextSize.Height == 0)
			{
				oTextSize.Height = oNode.GetFont().Height;
			}
			
			// draw check boxes
			if (oNode.GetCheckBoxes() == true && oNode.CheckBoxVisible == true)
			{												
				Pen oPen = null;		
			
				if (oNode.Flash == true)
					nAlpha = 255;

				#region draw check background
				if (oNode.GetCheckBackColor() != Color.Transparent)
				{
					if (oNode.Parent == null || oNode.Parent.SubNodesCheckExclusive == false)
					{
						Rectangle rectCheckBack = new Rectangle(nX + 4, nY + 2, 11, 11);
						Color backColor = Color.FromArgb(nAlpha, oNode.GetCheckBackColor());

						Brush brush = new SolidBrush(backColor);

						if (oNode.GetCheckBorderStyle() == CheckBoxBorderStyle.XP)
						{					
							Color fadeColor = oNode.GetCheckBackColor();
							if (fadeColor == Color.White)
								fadeColor = Color.LightGray;

							brush = new LinearGradientBrush
								(
								rectCheckBack,
								Color.FromArgb(nAlpha == 255 ? 255 : 48, fadeColor),
								Color.White,
								LinearGradientMode.ForwardDiagonal						
								);  
						}

						oGraphics.FillRectangle(brush, rectCheckBack);
						brush.Dispose();
						brush = null;
					}
					else
					{
						Rectangle rectCheckBack = new Rectangle(nX + 4, nY + 2, 11, 11);
						Color backColor = Color.FromArgb(nAlpha, oNode.GetCheckBackColor());

						Brush brush = new SolidBrush(backColor);

						if (oNode.GetCheckBorderStyle() == CheckBoxBorderStyle.XP)
						{					
							Color fadeColor = oNode.GetCheckBackColor();
							if (fadeColor == Color.White)
								fadeColor = Color.LightGray;

							brush = new LinearGradientBrush
								(
								rectCheckBack,
								Color.FromArgb(nAlpha == 255 ? 255 : 48, fadeColor),
								Color.White,
								LinearGradientMode.ForwardDiagonal						
								);  
						}

						GraphicsPath path = new GraphicsPath();
						path.AddEllipse(nX + 4, nY + 2, 10, 10);
						Region region = new Region(path);
						
						oGraphics.Clip = region;
						oGraphics.FillRectangle(brush, rectCheckBack);
						oGraphics.Clip = new Region(new Rectangle(0, 0, m_oTreeView.Width, m_oTreeView.Height));

						brush.Dispose();
						brush = null;
					}
				}
				#endregion

				oPen = new Pen(Color.FromArgb(nAlpha, oNode.GetCheckBorderColor()), 1);																	
				Rectangle rectCheck = new Rectangle(nX + 3, nY + 1, 12, 12);

				#region draw check rectangle

				if (oNode.Parent == null || oNode.Parent.SubNodesCheckExclusive == false)
				{
					if (oNode.GetCheckBorderStyle() == CheckBoxBorderStyle.Solid || oNode.GetCheckBorderStyle() == CheckBoxBorderStyle.XP)
						oGraphics.DrawRectangle(oPen, rectCheck);

					if (oNode.GetCheckBorderStyle() == CheckBoxBorderStyle.Dot)
					{
						oPen.DashStyle = DashStyle.Dot;
						oGraphics.DrawRectangle(oPen, rectCheck);
					}
				}
				else
				{
					if (oNode.GetCheckBorderStyle() == CheckBoxBorderStyle.Dot)					
						oPen.DashStyle = DashStyle.Dot;

					if (oNode.GetCheckBorderStyle() == CheckBoxBorderStyle.Solid || oNode.GetCheckBorderStyle() == CheckBoxBorderStyle.XP
						|| oNode.GetCheckBorderStyle() == CheckBoxBorderStyle.Dot)
						oGraphics.DrawEllipse(oPen, nX + 4, nY + 2, 10, 10);
				}

				oPen.DashStyle = DashStyle.Solid;
				#endregion

				m_mapItemCheckToRect.Add(oNode, rectCheck);
				m_mapRectToItemCheck.Add(rectCheck, oNode);

				if (oNode.Checked == true)
				{
					if (oNode.Parent == null || oNode.Parent.SubNodesCheckExclusive == false)
					{
						oPen.Color = Color.FromArgb(nAlpha, oNode.GetCheckCheckColor());
					
						oGraphics.DrawLine(oPen, nX + 6, nY + 6, nX + 6, nY + 8);
						oGraphics.DrawLine(oPen, nX + 7, nY + 7, nX + 7, nY + 9);
						oGraphics.DrawLine(oPen, nX + 8, nY + 8, nX + 8, nY + 10);
						oGraphics.DrawLine(oPen, nX + 9, nY + 7, nX + 9, nY + 9);
						oGraphics.DrawLine(oPen, nX + 10, nY + 6, nX + 10, nY + 8);
						oGraphics.DrawLine(oPen, nX + 11, nY + 5, nX + 11, nY + 7);
						oGraphics.DrawLine(oPen, nX + 12, nY + 4, nX + 12, nY + 6);
					}
					else
					{
						oPen.Color = Color.FromArgb(nAlpha, oNode.GetCheckCheckColor());

						oGraphics.DrawEllipse(oPen, nX + 6, nY + 4, 6, 6);
						oGraphics.DrawEllipse(oPen, nX + 7, nY + 5, 4, 4);
						oGraphics.DrawEllipse(oPen, nX + 8, nY + 6, 2, 2);						
						oGraphics.DrawEllipse(oPen, nX + 9, nY + 7, 1, 1);
						oGraphics.DrawRectangle(oPen, nX + 8, nY + 6, 2, 2);
					}
				}

				oPen.Dispose();

				nX += 17;
			}

			// paint the picture first if needed then draw the text
			if (oNode.Image != null)
			{								
				oGraphics.DrawImage(oNode.Image, 
					nX + 4, 
					nY + (int)(oTextSize.Height / 2.0) - (int)((float)oNode.Image.Height / 2.0) + 1,
					oNode.Image.Width, oNode.Image.Height);

				nX += oNode.Image.Width + 2;
			}
			else
			{
				if (oNode.ImageIndex != -1 && oNode.TreeView.ImageList != null 
					&& oNode.ImageIndex < oNode.TreeView.ImageList.Images.Count)
				{					
					oNode.TreeView.ImageList.Draw(oGraphics, nX + 2, 
						nY + (int)(oTextSize.Height / 2.0) - (int)((float)oNode.TreeView.ImageList.ImageSize.Height / 2.0), 
						oNode.TreeView.ImageList.ImageSize.Width,
						oNode.TreeView.ImageList.ImageSize.Height,
						oNode.ImageIndex);

					nX += oNode.TreeView.ImageList.ImageSize.Width;
				}
			}

			// get the right side of the text. if it is more far away than the width of the TreeView, truncate the text
			string sText = oNode.GetText();

			// render the text
			SolidBrush oTextBrush = new SolidBrush(Color.FromArgb(nAlpha, oNode.GetForeColor()));						

			// when draging the mouse over nodes, test if the node is being highlighted
			if (oNode == oNode.TreeView.HighlightedNode)
				oTextBrush.Color = oNode.GetHighlightedForeColor();

			Rectangle textRect = new Rectangle(nX + 2, nY, oNode.GetTreeView().GetDrawWidth() - nX - 15, 
				(int)oNode.GetTreeView().Height);

			SizeF textSize = oGraphics.MeasureString(StringDrawUtils.GetInstance().GetTextFromFormattedString(sText), oFont, 
				oNode.GetTreeView().GetDrawWidth() - nX - 15);			

			// clear the truncated flag
			oNode.TextTruncated = false;
 
			if (m_oTreeView.Multiline)
			{
				if (oNode.UseFormatting == true)
				{
					CharacterFormat chrFormat = new CharacterFormat(
						oFont, 
						oTextBrush, 
						0, 
						HotkeyPrefix.None, 
						true);

					ParagraphFormat paraFormat = new ParagraphFormat(
						ParagraphAlignment.Left, 
						ParagraphVerticalAlignment.Top, 
						true, 
						true, 
						StringTrimming.None, 
						Brushes.Transparent);

					StringDrawUtils.GetInstance().DrawStringInRectangle(oGraphics, sText, textRect, 
						chrFormat, paraFormat);
				}
				else
					oGraphics.DrawString(sText, oFont, oTextBrush, textRect);
			}
			else
			{
				sText = oNode.GetText();

				oTextSize = oGraphics.MeasureString(StringDrawUtils.GetInstance().GetTextFromFormattedString(sText), oFont);
				nTextWidth = (int)oTextSize.Width;

				if (nX + 2 + nTextWidth > m_oTreeView.m_LastNX)
					m_oTreeView.m_LastNX = nX + 2 + nTextWidth;

				if (nX + nTextWidth > oNode.GetTreeView().GetDrawWidth() - 15)
				{
					sText = StringDrawUtils.GetInstance().GetTextFromFormattedString(sText);

					float fChar = oTextSize.Width / float.Parse(sText.Length.ToString());

					int nChar = (int)((float)(nX + nTextWidth - oNode.GetTreeView().GetDrawWidth() + 15) / fChar) + 4;

					if (nChar < 0)
						nChar = 0;

					int nLength = sText.Length - nChar;
					if (nLength < 0)
						nLength = 0;

					sText = sText.Substring(0, nLength) + "...";
					oNode.TextTruncated = true;
				}
				
				// draw string (text) of the node in the proper system, based on the information whether it has formatting or not
				if (oNode.UseFormatting == true)
				{
					CharacterFormat chrFormat = new CharacterFormat(
						oFont, 
						oTextBrush, 
						0, 
						HotkeyPrefix.None, 
						true);

					StringDrawUtils.GetInstance().DrawString(oGraphics, sText,  new PointF(nX + 2, nY), 
						chrFormat, ParagraphAlignment.Left);
				}
				else
					oGraphics.DrawString(sText, oFont, oTextBrush, nX + 2, nY);				
			}

			if (m_oTreeView.Multiline == false)
				textSize = oGraphics.MeasureString(StringDrawUtils.GetInstance().GetTextFromFormattedString(sText), oFont);

			oTextBrush.Dispose();			

			// create the expand icon if specified
			if (oNode.GetShowSubitemsIndicator() == true && oNode.Nodes.Count > 0 && oNode.IsExpanded == false)
			{	
				int nIconX = (int)textRect.Left + (int)textSize.Width + 4;

				Pen oIndicatorPen = new Pen(Color.FromArgb(nAlpha, oNode.GetForeColor()), 1);
				oGraphics.DrawLine(oIndicatorPen, nIconX, nY + textSize.Height - 4, nIconX + 3, nY + textSize.Height - 4);
				oGraphics.DrawLine(oIndicatorPen, nIconX + 1, nY + textSize.Height - 5, nIconX + 3, nY + textSize.Height - 5);
				oGraphics.DrawLine(oIndicatorPen, nIconX + 2, nY + textSize.Height - 6, nIconX + 3, nY + textSize.Height - 6);
				oGraphics.DrawLine(oIndicatorPen, nIconX + 3, nY + textSize.Height - 6, nIconX + 3, nY + textSize.Height - 7);
				oIndicatorPen.Dispose();
			}

			if (oNode.Underline == true)
				PaintNodeUnderline(oNode, sText, oGraphics, nX, nY);
		}
		/// <summary>
		/// This one draws string into given rectangle with even some more limitations 
		/// than DrawStringInRectangle.<br/>
		/// It should not be called from anywhere else than DrawStringInRectangle.
		/// </summary>
		/// <param name="gr"></param>
		/// <param name="rect"></param>
		/// <param name="pf"></param>
		private void DrawStringLineByLine(Graphics gr, RectangleF rect, ParagraphFormat pf)
		{
			Interval i=Interval.Full(this);
			if(i.Empty)
				return;

			PointF pnt=rect.Location;
			float lineHeight=sdu.GetLineHeight(gr,InitialFormat.Font);

			int maxLineCount=GetMaxVisibleLineCount(gr, rect.Size.Height,pf);
			int lineIndex=0;

			Position nl=IndexOf('\n',i);
			while (!nl.IsEnd() && lineIndex<maxLineCount-1)
			{
				Interval iOld, iNew;
				i.Split(nl, out iOld, out iNew);
				iNew.Start++;

				if( (!iOld.Empty) && this[iOld.End-1]=='\r' )
					iOld.End--;

				DrawSingleLineAligned(gr,pnt,rect.Width,iOld,pf, false);
				pnt.Y+=lineHeight;

				i=iNew;
				nl=IndexOf('\n',i);

				lineIndex++;
			}
			if(nl.IsEnd())
				DrawSingleLineAligned(gr,pnt,rect.Width,i,pf, false);
			else
				DrawSingleLineAligned(gr,pnt,rect.Width,i,pf, true);
		}
		/// <summary>
		/// Returns <see cref="StringFormat"/> object that fits best to given <see cref="CharacterFormat"/>
		/// and <see cref="ParagraphFormat"/> objects.
		/// </summary>
		/// <param name="fmtCharacter"><see cref="CharacterFormat"/> object</param>
		/// <param name="fmtParagraph"><see cref="ParagraphFormat"/> object</param>
		/// <returns><see cref="StringFormat"/> object</returns>
		internal StringFormat GetStringFormat(CharacterFormat fmtCharacter, ParagraphFormat fmtParagraph)
		{
			StringFormat sf = (StringFormat) StringFormat.GenericDefault.Clone();
			sf.Alignment = ParAl2StrAl(fmtParagraph.Alignment);
			sf.LineAlignment = ParVertAl2StrAl(fmtParagraph.VerticalAlignment);
			sf.HotkeyPrefix = fmtCharacter.HotkeyPrefix;
			sf.Trimming = fmtParagraph.Trimming;
			if (!fmtParagraph.ShowIncompleteLines)
				sf.FormatFlags |= StringFormatFlags.LineLimit;
			if (!fmtParagraph.MultiLine)
				sf.FormatFlags |= StringFormatFlags.NoWrap;
			return sf;
		}
		/// <summary>
		/// Returns Image with <paramref name="str"/> drawn into rectangle of given size.
		/// </summary>
		/// <param name="str"><see cref="string"/> to be drawn.</param>
		/// <param name="size">Size of rectangle string will be drawn into and also of the 
		/// returned image.</param>
		/// <param name="fmtCharacter"><see cref="CharacterFormat"/> used to draw the <paramref name="str"/>. </param>
		/// <param name="fmtParagraph"><see cref="ParagraphFormat"/> used to draw the <paramref name="str"/>. </param>
		/// <param name="topLeftOffset">Out parameter which receives top-left point of the rotated string. </param>
		/// <returns><see cref="Image"/> with given <paramref name="str"/> drawn.</returns>
		public Image DrawStringInRectangle(string str, SizeF size,
		                                   CharacterFormat fmtCharacter, ParagraphFormat fmtParagraph,
		                                   out PointF topLeftOffset)
		{
			//Prepare mask
			CharacterFormat mcf = fmtCharacter.ShallowCopy();
			ParagraphFormat mpf = fmtParagraph.ShallowCopy();
			mcf.Brush = new SolidBrush(Color.Black);
			mpf.BackgroundBrush = new SolidBrush(Color.White);
			mcf.IgnoreColorFormatting = true;
			Bitmap bMask = (Bitmap) DrawSolidBackgroundStringInRectangle(str, size, mcf,
			                                                             mpf, out topLeftOffset);

			//Prepare foreground
			CharacterFormat fgcf = fmtCharacter.ShallowCopy();
			ParagraphFormat fgpf = fmtParagraph.ShallowCopy();
			fgcf.FilledBounds = true;
			fgpf.BackgroundBrush = null;

			Bitmap bFg = (Bitmap) DrawSolidBackgroundStringInRectangle(str, size, fgcf,
			                                                           fgpf, out topLeftOffset);

			//And blend it together
			CopyIntensityAsAlpha(bMask, bFg);

			bMask.Dispose();

			//Using background
			if (fmtParagraph.BackgroundBrush != null)
			{
				Bitmap bRes = new Bitmap(bFg.Width, bFg.Height);
				Graphics rsgr = Graphics.FromImage(bRes); //resulting bitmap's graphics


				if (fmtCharacter.Angle == 0)
					rsgr.FillRectangle(fmtParagraph.BackgroundBrush, 0, 0, size.Width, size.Height);
				else
				{
					Matrix trOld = rsgr.Transform.Clone();
					rsgr.TranslateTransform(topLeftOffset.X, topLeftOffset.Y);
					rsgr.RotateTransform(fmtCharacter.Angle);

					rsgr.FillRectangle(fmtParagraph.BackgroundBrush, 0, 0, size.Width, size.Height);

					rsgr.Transform = trOld;
				}

				rsgr.DrawImage(bFg, 0, 0);
				rsgr.Dispose();
				bFg.Dispose();
				return bRes;
			}
			else
			{
				return bFg;
			}
		}
		/// <summary>
		/// Draws trimmed line with trimming specified in ParagraphFormat.Trimming.
		/// </summary>
		/// <param name="gr"></param>
		/// <param name="pnt"></param>
		/// <param name="width"></param>
		/// <param name="i"></param>
		/// <param name="pf"></param>
		private void DrawTrimmedLine(Graphics gr, PointF pnt, float width, 
			Interval i, ParagraphFormat pf)
		{
			if(i.Empty)
				return;

			bool showEllipsis;
			Interval si;//shown interval

			GetTrimmingInfo(gr, width, i, pf, out si, out showEllipsis);

			PointF pos=pnt;
			Position nl;
			Interval iOld, iNew;
			while( (nl=IndexOf('\n', si)) <si.End )
			{
				si.Split(nl, out iOld, out iNew);
				DrawSingleLineUnaligned(gr, pos, iOld);
				pos.X+=Measure(gr,iOld,true).Width - 
					2*sdu.GetMeasureStringHorizontalGap(gr, GetCharacterFormat(iOld.End).Font);

				iNew.Start++;
				si=iNew;
			}
			DrawSingleLineUnaligned(gr, pos, si);
			if(showEllipsis)
			{
				pos.X+=Measure(gr,si,true).Width - 
					2*sdu.GetMeasureStringHorizontalGap(gr, GetCharacterFormat(si.End).Font);
				if(si.End.IsEnd())
					si.End--;
				sdu.DrawString(gr, ellipsisString, pos,GetCharacterFormat(si.End));
			}
		}
		/// <summary>
		/// Returns size of given line if it's drawn as trimmed.
		/// </summary>
		/// <param name="gr"></param>
		/// <param name="width"></param>
		/// <param name="i"></param>
		/// <param name="pf"></param>
		/// <returns></returns>
		private SizeF MeasureTrimmedLine(Graphics gr, float width, Interval i, ParagraphFormat pf)
		{
			bool showEllipsis;
			Interval shown;
			GetTrimmingInfo(gr, width, i, pf, out shown, out showEllipsis);
			SizeF res=MeasureIgnoringNewlines(gr, shown);
			if(showEllipsis)
			{
				float ellipsisWidth=gr.MeasureString(ellipsisString, InitialFormat.Font).Width;
				res.Width+=ellipsisWidth;
			}
			return res;
		}
		/// <summary>
		/// Draws string with given character format and alignment at given <see cref="Point"/>.
		/// </summary>
		/// <param name="gr"><see cref="Graphics"/> object to draw into.</param>
		/// <param name="str"><see cref="string"/> to be drawn.</param>
		/// <param name="pnt"><see cref="Point"/> where the string will be drawn.</param>
		/// <param name="fmt"><see cref="CharacterFormat"/> used to draw the <see cref="string"/>. </param>
		/// <param name="align">Specifies whether the <paramref name="pnt"/> is at left, right 
		/// or in the center of the string. (<see cref="ParagraphAlignment.Full"/> means the same
		/// as <see cref="ParagraphAlignment.Left"/>.)</param>
		public void DrawString(Graphics gr, string str, PointF pnt,
		                       CharacterFormat fmt, ParagraphAlignment align)
		{
			StringFormat sf = (StringFormat) StringFormat.GenericDefault.Clone();
			sf.Alignment = ParAl2StrAl(align);
			sf.HotkeyPrefix = fmt.HotkeyPrefix;

			Matrix trOld = null;
			if (fmt.Angle != 0)
			{
				trOld = gr.Transform.Clone();
				gr.TranslateTransform(pnt.X, pnt.Y);
				gr.RotateTransform(fmt.Angle);
				gr.TranslateTransform(-pnt.X, -pnt.Y);
			}

			if (fmt.Formatted)
			{
				CharacterFormat cf = fmt.ShallowCopy();
				cf.Angle = 0;
				SDUFormattedString fs = new SDUFormattedString(str, cf);
				SizeF sz = fs.Measure(gr, true);
				sz.Height += GetMeasureStringVerticalGap(gr, cf.Font);

				PointF ofs = pnt;
				switch (align)
				{
					case ParagraphAlignment.Right:
						ofs.X -= sz.Width;
						break;
					case ParagraphAlignment.Center:
						ofs.X -= sz.Width/2;
						break;
				}

				ParagraphFormat pf = new ParagraphFormat();
				pf.MultiLine = false;
				pf.Alignment = align;
				fs.DrawStringInRectangle(gr, new RectangleF(ofs, sz), pf);


			}
			else if (fmt.FilledBounds)
			{
				ParagraphFormat pf = new ParagraphFormat();
				//pf.Alignment=align;
				SizeF sz = MeasureStringExactly(gr, str, fmt, pf, false);

				sz.Width += GetMeasureStringHorizontalGap(gr, fmt.Font);
				pnt.X += GetMeasureStringHorizontalGap(gr, fmt.Font)/2;
				pnt.Y += GetMeasureStringVerticalGap(gr, fmt.Font);

				gr.FillRectangle(fmt.Brush, new RectangleF(pnt, sz));
			}
			else
				gr.DrawString(str, fmt.Font, fmt.Brush, pnt, sf);

			if (trOld != null)
				gr.Transform = trOld;
		}
		/// <summary>
		/// Draws string with given formating and width at specified point.
		/// </summary>
		/// <param name="img"><see cref="Image"/> object to draw into.</param>
		/// <param name="str"><see cref="string"/> to be drawn.</param>
		/// <param name="width">Width that string will be wrapped to.</param>
		/// <param name="ofs">Top-left point of the drawn string.</param>
		/// <param name="fmtCharacter"><see cref="CharacterFormat"/> used to draw the <see cref="string"/>. </param>
		/// <param name="fmtParagraph"><see cref="ParagraphFormat"/> used to draw the <see cref="string"/>. </param>
		public void DrawWrappedString(Image img, string str, PointF ofs, float width,
			CharacterFormat fmtCharacter, ParagraphFormat fmtParagraph)
		{
			Graphics gr = Graphics.FromImage(img);
			DrawWrappedString(gr, str, ofs, width, fmtCharacter, fmtParagraph);
			gr.Dispose();
		}
Exemple #10
0
		/// <summary>
		/// Draws string with given formating and width at specified point.
		/// </summary>
		/// <param name="gr"><see cref="Graphics"/> object to draw into.</param>
		/// <param name="str"><see cref="string"/> to be drawn.</param>
		/// <param name="width">Width that string will be wrapped to.</param>
		/// <param name="ofs">Top-left point of the drawn string.</param>
		/// <param name="fmtCharacter"><see cref="CharacterFormat"/> used to draw the <see cref="string"/>. </param>
		/// <param name="fmtParagraph"><see cref="ParagraphFormat"/> used to draw the <see cref="string"/>. </param>
		public void DrawWrappedString(Graphics gr, string str, PointF ofs, float width,
			CharacterFormat fmtCharacter, ParagraphFormat fmtParagraph)
		{
			float height=GetWrappedHeight(gr, str, fmtCharacter, width);
			ParagraphFormat pf2=fmtParagraph.ShallowCopy();
			pf2.MultiLine=true;
			pf2.ShowIncompleteLines=true;
			pf2.VerticalAlignment=ParagraphVerticalAlignment.Top;
			DrawStringInRectangle(gr, str, new RectangleF(ofs, 
				new SizeF(width, height)),fmtCharacter, fmtParagraph);
		}
Exemple #11
0
		/// <summary>
		/// Draws string with given formating into given <paramref name="rectangle"/>.
		/// </summary>
		/// <param name="gr"><see cref="Graphics"/> object to draw into.</param>
		/// <param name="str"><see cref="string"/> to be drawn.</param>
		/// <param name="rectangle"><see cref="Rectangle"/> that string is drawn into.</param>
		/// <param name="fmtCharacter"><see cref="CharacterFormat"/> used to draw the <see cref="string"/>. </param>
		/// <param name="fmtParagraph"><see cref="ParagraphFormat"/> used to draw the <see cref="string"/>. </param>
		public void DrawStringInRectangle(Graphics gr, string str, RectangleF rectangle,
		                                  CharacterFormat fmtCharacter, ParagraphFormat fmtParagraph)
		{
			Matrix trOld = gr.Transform.Clone();
			gr.TranslateTransform(rectangle.X, rectangle.Y);
			gr.RotateTransform(fmtCharacter.Angle);
			gr.TranslateTransform(-rectangle.X, -rectangle.Y);

			if (fmtParagraph.BackgroundBrush != null)
				gr.FillRectangle(fmtParagraph.BackgroundBrush, rectangle);

			CharacterFormat cf = fmtCharacter.ShallowCopy();
			cf.Angle = 0;
			ParagraphFormat pf = fmtParagraph.ShallowCopy();
			pf.BackgroundBrush = null;

			if (fmtCharacter.Formatted)
			{
				SDUFormattedString fmts = new SDUFormattedString(str, cf);
				if (pf.MultiLine)
					fmts.WrapLines(gr, rectangle.Width);
				fmts.DrawStringInRectangle(gr, rectangle, pf);
			}
			else if (fmtCharacter.FilledBounds)
				gr.FillRectangle(fmtCharacter.Brush, rectangle);
			else
			{
				if (fmtParagraph.Alignment == ParagraphAlignment.Full && fmtParagraph.MultiLine && rectangle.Width > 0)
				{
					DrawFullAlignedStringInRectangle(gr, str, rectangle, cf, fmtParagraph);
				}
				else
				{
					StringFormat sf = GetStringFormat(fmtCharacter, fmtParagraph);

					gr.DrawString(str, fmtCharacter.Font, fmtCharacter.Brush, rectangle, sf);

				}
			}

			gr.Transform = trOld;

		}
Exemple #12
0
		/// <summary>
		/// Returns (more or less) exact size of given string.
		/// </summary>
		/// <param name="gr">Graphics where the size should be measured.</param>
		/// <param name="str">String to be measured.</param>
		/// <param name="cf">CharacterFormat of the string.</param>
		/// <param name="pf">ParagraphFormat of the string.</param>
		/// <param name="includeTrailingSpaces">Specifies whether trailing 
		/// spaces should be included into measurement.</param>
		/// <returns>Returns size of given text at specified conditions.</returns>
		/// <remarks>
		/// Returned value is not affected by any gaps and inaccurancies which appear
		/// while using Graphics.MeasureString as we use Graphics.MeasureCharacterRanges.
		/// </remarks>
		public SizeF MeasureStringExactly(Graphics gr, string str, CharacterFormat cf, ParagraphFormat pf,
		                                  bool includeTrailingSpaces)
		{
			StringFormat sf = GetStringFormat(cf, pf);

			if (includeTrailingSpaces)
				sf.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;


			sf.SetMeasurableCharacterRanges(new CharacterRange[] {new CharacterRange(0, str.Length)});
			sf.FormatFlags |= StringFormatFlags.NoWrap;

			SizeF bound = gr.MeasureString(str, (cf).Font, 0, sf);
			bound.Width += 10;
			bound.Height += 10;
			RectangleF rect = new RectangleF(new PointF(0, 0), bound);

			//RectangleF rect=new RectangleF(0,0,0,0);

			bool useOriginalGraphics = gr.DpiX != dummyGraphics.DpiX ||
				gr.DpiY != dummyGraphics.DpiY ||
				gr.PageScale != dummyGraphics.PageScale ||
				gr.PageUnit != dummyGraphics.PageUnit;

			Region[] rgn;

			if (useOriginalGraphics)
				rgn = gr.MeasureCharacterRanges(str, cf.Font, rect, sf);
			else
				rgn = dummyGraphics.MeasureCharacterRanges(str, cf.Font, rect, sf);

			sf.Dispose();

			SizeF size;

			if (useOriginalGraphics)
				size = rgn[0].GetBounds(gr).Size;
			else
				size = rgn[0].GetBounds(dummyGraphics).Size;

			rgn[0].Dispose();

			return size;
		}
Exemple #13
0
		/// <summary>
		/// Draws full aligned string into given rectangle.
		/// </summary>
		/// <param name="gr"><see cref="Graphics"/> object to draw into.</param>
		/// <param name="str"><see cref="string"/> to be drawn.</param>
		/// <param name="rect"><see cref="Rectangle"/> that string is drawn into.</param>
		/// <param name="cf"><see cref="CharacterFormat"/> used to draw the <paramref name="str"/>. </param>
		/// <param name="pf"><see cref="ParagraphFormat"/> used to draw the <paramref name="str"/>. </param>
		/// <remarks>As this method isn't to be exposed as public, there are 
		/// several limitations:<br/>
		/// <see cref="Rectangle.Width"/> has to be non-zero.<br/>
		/// <see cref="CharacterFormat.Angle"/> has to be zero.<br/>
		/// <see cref="ParagraphFormat.MultiLine"/> has to be false.<br/>
		/// <see cref="ParagraphFormat.Alignment"/> has to be <see cref="ParagraphAlignment.Full"/>.<br/>
		/// <see cref="ParagraphFormat.BackgroundBrush"/> has to be null.<br/>
		/// If not satisfied, results might be not as expected.</remarks>
		private void DrawFullAlignedStringInRectangle(Graphics gr, string str, RectangleF rect,
		                                              CharacterFormat cf, ParagraphFormat pf)
		{
			Region oldClip = gr.Clip.Clone();
			gr.IntersectClip(rect);

			float yofs = rect.Y;

			StringFormat sfLeft; //StringFormat for drawing left-aligned lines
			{
				ParagraphFormat pf2 = pf.ShallowCopy();
				pf2.Alignment = ParagraphAlignment.Left;
				pf2.VerticalAlignment = ParagraphVerticalAlignment.Top;
				pf2.MultiLine = false;
				pf2.ShowIncompleteLines = true;
				sfLeft = GetStringFormat(cf, pf2);
			}


			//lineHeight & borders retrieving
			float lineHeight = GetLineHeight(gr, cf.Font);

			int lineCount;

			//lineCount retrieving
			{
				StringFormat sf = GetStringFormat(cf, pf);
				int charfit;
				gr.MeasureString(str, cf.Font, new SizeF(rect.Width, rect.Height), sf,
				                 out charfit, out lineCount);
			}


			//VerticalAlignment business
			switch (pf.VerticalAlignment)
			{
				case ParagraphVerticalAlignment.Bottom:
					yofs += rect.Height - lineHeight*lineCount;
					break;
				case ParagraphVerticalAlignment.Center:
					yofs += (rect.Height - lineHeight*lineCount)/2;
					break;
			}


			int flc = 0; //first line character
			int llc = flc; //last line character (actually the one after last)
			int lineIndex = 0;
			while (lineIndex < lineCount - 1 && flc < str.Length)
			{
				lineIndex++;

				llc = flc;

				//add spaces at the beginneing
				while (llc < str.Length && Char.IsWhiteSpace(str, llc))
					llc++;

				//add words until the line is full
				int pllc = llc; //potential last line character
				while (llc == pllc && llc < str.Length)
				{
					pllc++;
					while (pllc < str.Length && !Char.IsWhiteSpace(str, pllc))
						pllc++;
					if (gr.MeasureString(str.Substring(flc, pllc - flc), cf.Font).Width < rect.Width)
						llc = pllc;
				}

				//If nothing was added before, add single characters (rect.Width is too small)
				if (llc == flc)
					do
					{ //always at least one character per line
						llc++;
					} while (llc < str.Length && gr.MeasureString(str.Substring(flc, llc - flc + 1), cf.Font).Width < rect.Width);

				string line = str.Substring(flc, llc - flc);

				//Newline fotmatting
				int nlindex = line.IndexOf('\n');
				if (nlindex >= 0)
				{
					//Newline may be just "\n" or "\r\n"
					if (nlindex > 1 && line[nlindex - 1] == '\r')
						line = line.Substring(0, nlindex - 1);
					else
						line = line.Substring(0, nlindex);

					DrawString(gr, line, new PointF(rect.X, yofs), cf);

					flc += nlindex + 1;
				}
				else
				{
					DrawFullAlignedLine(gr, line, new PointF(rect.X, yofs), rect.Width, cf);

					flc = llc;
					//skip spaces at the end of line (just like Graphics.DrawString does)
					while (flc < str.Length && Char.IsWhiteSpace(str, flc))
						flc++;
				}

				yofs += lineHeight;

			}

			//And here comes the last line - it's always drawn left-aligned
			//(also, we have to get rid of newlines or they will sometimes show
			//in the bottom)

			gr.DrawString(str.Substring(flc), cf.Font, cf.Brush,
			              new RectangleF(rect.X, yofs, rect.Width, lineHeight), sfLeft);

			//Set back the original clipping region
			gr.Clip = oldClip;

		}
Exemple #14
0
		/// <summary>
		/// Returns an image with given string drawn. As in this method is not present the
		/// ClearType bug correction, it's only to be used with solid background brush.<br/>
		/// Merit of this method is that it can properly handle rotated text.
		/// </summary>
		private Image DrawSolidBackgroundStringInRectangle(string str, SizeF size,
		                                                   CharacterFormat fmtCharacter, ParagraphFormat fmtParagraph, out PointF topLeftOffset)
		{
			float angle = fmtCharacter.Angle%360;
			float nAngle = (float) ((angle%90)*Math.PI/180); //normalized angle in RADIANS!
			PointF nOfs;
			SizeF nSize;
			if (nAngle == 0 || fmtCharacter.Angle == 0)
			{
				nOfs = new PointF(0, 0);
				nSize = size;
			}
			else
			{
				nOfs = new PointF((float) Math.Sin(nAngle)*size.Height, 0);
				nSize = new SizeF(
					(float) (Math.Cos(nAngle)*size.Width + Math.Sin(nAngle)*size.Height),
					(float) (Math.Sin(nAngle)*size.Width + Math.Cos(nAngle)*size.Height));
			}

			PointF rOfs; //Rotated top-left point
			SizeF rSize; //Rotated size
			if (angle < 90f)
			{
				rSize = nSize;
				rOfs = nOfs;
			}
			else if (angle < 180f)
			{
				rSize = new SizeF(nSize.Height, nSize.Width); //yes, width=height and height=width
				rOfs = new PointF(rSize.Width, nOfs.X);
			}
			else if (angle < 270f)
			{
				rSize = nSize;
				rOfs = new PointF(rSize.Width - nOfs.X, rSize.Height);
			}
			else
			{
				rSize = new SizeF(nSize.Height, nSize.Width); //yes, width=height and height=width
				rOfs = new PointF(0, rSize.Height - nOfs.X);
			}

			topLeftOffset = rOfs;

			Bitmap res = new Bitmap(Size.Ceiling(rSize).Width, Size.Ceiling(rSize).Height);

			Graphics gr = Graphics.FromImage(res);
			DrawStringInRectangle(gr, str, new RectangleF(rOfs, size), fmtCharacter, fmtParagraph);
			gr.Dispose();
			return res;
		}
		/// <summary>
		/// Measures part of the text. This part of text must all have the same formatting
		/// (ie. must be stored in the same item of m_strings).
		/// </summary>
		/// <param name="gr"></param>
		/// <param name="piece"></param>
		/// <param name="start"></param>
		/// <param name="end"></param>
		/// <param name="trailingSpaces"></param>
		/// <returns></returns>
		private SizeF MeasurePiece(Graphics gr, int piece, int start, int end, bool trailingSpaces)
		{
			if(piece>=Count)
			{
				return new SizeF(0,sdu.GetLineHeight(gr,InitialFormat.Font));
			}

			if(end>this[piece].Length)
				end=this[piece].Length;

			if(start>=end)
			{
				return new SizeF(0,sdu.GetLineHeight(gr,InitialFormat.Font));
			}

			ParagraphFormat pf = new ParagraphFormat(ParagraphAlignment.Left, ParagraphVerticalAlignment.Top,
				false,true, StringTrimming.None, null);
			CharacterFormat cf=GetCharacterFormat(piece);
			
			string str=this[piece].Substring(start, end-start);


			SizeF size=sdu.MeasureStringExactly(gr,str,cf, pf, trailingSpaces);

			return size;
		}
Exemple #16
0
		/// <summary>
		/// Draws string with given formating into given rectangle.
		/// </summary>
		/// <param name="img"><see cref="Image"/> object to draw into.</param>
		/// <param name="str"><see cref="string"/> to be drawn.</param>
		/// <param name="rect"><see cref="Rectangle"/> that string is drawn into.</param>
		/// <param name="fmtCharacter"><see cref="CharacterFormat"/> used to draw the <paramref name="str"/>. </param>
		/// <param name="fmtParagraph"><see cref="ParagraphFormat"/> used to draw the <paramref name="str"/>. </param>
		/// <remarks>There's a problem while drawing strings using ClearType on transparent 
		/// background. Resulting text is going to look thick and jagged. If this applies to you, use
		/// rather Image DrawString(string, CharacterFormat) or 
		/// Image DrawStringInRectangle(string, SizeF, CharacterFormat, ParagraphFormat) where the 
		/// problem is corrected (at cost of a slight performance loss).</remarks>
		public void DrawStringInRectangle(Image img, string str, RectangleF rect,
		                                  CharacterFormat fmtCharacter, ParagraphFormat fmtParagraph)
		{
			Graphics gr = Graphics.FromImage(img);
			DrawStringInRectangle(gr, str, rect, fmtCharacter, fmtParagraph);
			gr.Dispose();
		}
		/// <summary>
		/// Returns maximum visible line count based on give height and 
		/// line height of used font.
		/// </summary>
		/// <param name="gr"></param>
		/// <param name="height"></param>
		/// <param name="pf"></param>
		/// <returns></returns>
		private int GetMaxVisibleLineCount(Graphics gr, float height, ParagraphFormat pf)
		{
			float res=height/sdu.GetLineHeight(gr,InitialFormat.Font);
			if(pf.ShowIncompleteLines)
				return (int)Math.Ceiling(res);
			else
				return (int)Math.Floor(res);
		}
Exemple #18
0
		/// <summary>
		/// Returns <see cref="Image"/> object with <paramref name="str"/> drawn.
		/// </summary>
		/// <param name="str"><see cref="string"/> to be drawn.</param>
		/// <param name="fmt"><see cref="CharacterFormat"/> used to draw the <paramref name="str"/>. </param>
		/// <returns><see cref="Image"/> with given <paramref name="str"/> drawn. The image is sized
		/// just to fit the string.</returns>
		public Image DrawString(string str, CharacterFormat fmt)
		{
			/*Size size=Size.Ceiling(dummyGraphics.MeasureString(str, fmt.Font));
			Image res=new Bitmap(size.Width, size.Height);
			DrawString(res, str, new Point(0,0), fmt);
			return res;*/
			ParagraphFormat pf = new ParagraphFormat(ParagraphAlignment.Left, ParagraphVerticalAlignment.Top,
			                                         false, true, StringTrimming.None, null);
			SizeF sz = MeasureStringExactly(dummyGraphics, str, fmt, new ParagraphFormat(), true);
			sz.Width += 2*GetMeasureStringVerticalGap(dummyGraphics, fmt.Font);
			sz.Height += 2*GetMeasureStringHorizontalGap(dummyGraphics, fmt.Font);

			if ((fmt.Font.Style & FontStyle.Italic) != 0)
				sz.Width += 4;
			else
				sz.Width += 2;


			return DrawStringInRectangle(str, sz, fmt, pf);
		}
		/// <summary>
		/// Sets out parameters with informations needed to trim the line correctly.<br/>
		/// </summary>
		/// <param name="gr"></param>
		/// <param name="width"></param>
		/// <param name="i"></param>
		/// <param name="pf"></param>
		/// <param name="shownInterval"></param>
		/// <param name="showEllipsis"></param>
		private void GetTrimmingInfo(Graphics gr, float width, Interval i, ParagraphFormat pf, 
			out Interval shownInterval, out bool showEllipsis)
		{
			//First we have to decide whether the ellipsis symbol will be shown
			switch(pf.Trimming)
			{
				case StringTrimming.EllipsisPath: 
				case StringTrimming.EllipsisCharacter: 
				case StringTrimming.EllipsisWord: 
					showEllipsis=true;
					break;
				case StringTrimming.Character:
				case StringTrimming.Word:
				case StringTrimming.None:
				default:
					showEllipsis=false;
					break;
			}

			
			Interval si; //"shownInterval" abbreviation
			Position nl;

			float remainingWidth;
			if(showEllipsis)
			{
				float ellipsisWidth=gr.MeasureString(ellipsisString, InitialFormat.Font).Width;
				remainingWidth=width-ellipsisWidth;
			} 
			else 
				remainingWidth=width;

			
			//And now lets compute the shown interval
			switch(pf.Trimming)
			{
				case StringTrimming.EllipsisWord: 
					si=i;
					nl=IndexOf('\n', i);
					si.End=(nl<i.End)?(nl):(i.End);

					while((!si.Empty) && Char.IsWhiteSpace(this[si.End-1]))
						si.End--;
					while( (!si.Empty) && MeasureIgnoringNewlines(gr,si).Width>remainingWidth)
					{
						while((!si.Empty) && !Char.IsWhiteSpace(this[si.End-1]))
							si.End--;
						while((!si.Empty) && Char.IsWhiteSpace(this[si.End-1]))
							si.End--;
					}

					break;
					//ellipsisPath is quite problematic and not very often used, 
					//so let's ignore it :-)
				case StringTrimming.EllipsisPath: 
				case StringTrimming.EllipsisCharacter: 
				case StringTrimming.Character:
					si=i;
					nl=IndexOf('\n', i);
					if(nl<i.End && IsWrappingNL(nl) )
					{
						Position nnl=IndexOf('\n',new Interval(nl+1, i.End));
						if(nnl<i.End)
							si.End=nnl;
						else
							si.End=i.End;
					} 
					else
						si.End=(nl<i.End)?(nl):(i.End);

					while( ( (showEllipsis &&(!si.Empty)) || si.Length>1 ) 
						&& MeasureIgnoringNewlines(gr, si).Width>remainingWidth)
						si.End--;

					break;


				case StringTrimming.Word:
					si=i;
					nl=IndexOf('\n', i);
					si.End=(nl<i.End)?(nl):(i.End);

					break;

				
				case StringTrimming.None:
				default:
					si=i;
					nl=IndexOf('\n', i);
					if(nl<i.End && IsWrappingNL(nl) )
					{
						Position nnl=IndexOf('\n',new Interval(nl+1, i.End));
						if(nnl<i.End)
							si.End=nnl;
						else
							si.End=i.End;
					}
					si.End=(nl<i.End)?(nl):(i.End);

					break;
			}

			shownInterval=si;
		}
Exemple #20
0
		/// <summary>
		/// Returns Image with <paramref name="str"/> drawn wrapped to given <paramref name="width"/>.
		/// </summary>
		/// <param name="str"><see cref="string"/> to be drawn.</param>
		/// <param name="width">Width that string will be wrapped to.</param>
		/// <param name="fmtCharacter"><see cref="CharacterFormat"/> used to draw the <see cref="string"/>. </param>
		/// <param name="fmtParagraph"><see cref="ParagraphFormat"/> used to draw the <see cref="string"/>. </param>
		/// <returns><see cref="Image"/> with given <paramref name="str"/> drawn.</returns>
		public Image DrawWrappedString(string str, float width,
		                               CharacterFormat fmtCharacter, ParagraphFormat fmtParagraph)
		{
			float height = GetWrappedHeight(DummyGraphics, str, fmtCharacter, width);
			ParagraphFormat pf2 = fmtParagraph.ShallowCopy();
			pf2.MultiLine = true;
			pf2.ShowIncompleteLines = true;
			pf2.VerticalAlignment = ParagraphVerticalAlignment.Top;
			return DrawStringInRectangle(str, new SizeF(width, height), fmtCharacter, fmtParagraph);
		}
		/// <summary>
		/// Draws string into specified rectangle using given ParagraphFormat.
		/// </summary>
		/// <param name="gr"></param>
		/// <param name="rect"></param>
		/// <param name="pf"></param>
		/// <remarks>
		/// This is the 'main' method of the class. This one is called by StringDrawUtils
		/// to draw formatted string.<br/>
		/// As this class (and consequently this method) isn't to be published, there are some limitations:<br/>
		/// Angle of InitialFormat (specified at construction) has to be zero.<br/>
		/// BackgroundBrush
		/// </remarks>
		public void DrawStringInRectangle(Graphics gr, RectangleF rect, ParagraphFormat pf)
		{
			Debug.Assert(InitialFormat.Angle==0);
			Debug.Assert(pf.BackgroundBrush==null);


			if(pf.VerticalAlignment!=ParagraphVerticalAlignment.Top)
			{
				int lines=Math.Min(GetMaxVisibleLineCount(gr, rect.Height, pf), 
					CountOf(Interval.Full(this), '\n')+1);
				float lineHeight=sdu.GetLineHeight(gr,InitialFormat.Font);
				float totalHeight=(lineHeight*lines)+
					sdu.GetMeasureStringVerticalGap(gr, InitialFormat.Font);

				switch(pf.VerticalAlignment)
				{
					case ParagraphVerticalAlignment.Bottom:
						rect.Offset(0, rect.Height-totalHeight);
						break;
					case ParagraphVerticalAlignment.Center:
						rect.Offset(0, (rect.Height-totalHeight)/2);
						break;
				}
			}

			
			Region oldClip=gr.Clip.Clone();

			gr.IntersectClip(rect);

			DrawStringLineByLine(gr, rect, pf);

			gr.Clip=oldClip;

		}
Exemple #22
0
		/// <summary>
		/// Returns Image with <paramref name="str"/> drawn into rectangle of given size.
		/// </summary>
		/// <param name="str"><see cref="string"/> to be drawn.</param>
		/// <param name="size">Size of rectangle string will be drawn into and also of the 
		/// returned image.</param>
		/// <param name="fmtCharacter"><see cref="CharacterFormat"/> used to draw the <paramref name="str"/>. </param>
		/// <param name="fmtParagraph"><see cref="ParagraphFormat"/> used to draw the <paramref name="str"/>. </param>
		/// <returns><see cref="Image"/> with given <paramref name="str"/> drawn.</returns>
		public Image DrawStringInRectangle(string str, SizeF size,
		                                   CharacterFormat fmtCharacter, ParagraphFormat fmtParagraph)
		{
			PointF tmp;
			return DrawStringInRectangle(str, size, fmtCharacter, fmtParagraph, out tmp);
		}