/// <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>
		/// 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 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);
		}
		/// <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;

		}
		/// <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;

		}