public static int CharacterLength(char c, float fontSize, string fontName) { System.Drawing.Bitmap holderBmp = new System.Drawing.Bitmap(1, 1); System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(holderBmp); //bool needRF = needRefresh; if (c == ' ') { } string text = "" + c; System.Drawing.SizeF size = g.MeasureString(text, new System.Drawing.Font(fontName, fontSize)); System.Drawing.Font font = new System.Drawing.Font(fontName, fontSize); System.Drawing.StringFormat format = new System.Drawing.StringFormat(); format.FormatFlags = System.Drawing.StringFormatFlags.MeasureTrailingSpaces; System.Drawing.CharacterRange[] ranges = new System.Drawing.CharacterRange[] { new System.Drawing.CharacterRange(0, 1) }; format.SetMeasurableCharacterRanges(ranges); System.Drawing.Rectangle sdRect = new System.Drawing.Rectangle(0, 0, (int)(size.Width + 0.5), (int)(size.Height + 0.5)); System.Drawing.Region[] regions = g.MeasureCharacterRanges(text, font, sdRect, format); System.Drawing.RectangleF rectF = regions[0].GetBounds(g); //needRefresh = needRF; holderBmp.Dispose(); return((int)(rectF.Width * (c == ' ' ? 1.7 : 1) + 0.5)); }
//====================================== public Size MeasureString(char[] buff, int startAt, int len, Font font) { _characterRanges[0] = new System.Drawing.CharacterRange(0, len); _stringFormat.SetMeasurableCharacterRanges(_characterRanges); System.Drawing.Font font2 = (System.Drawing.Font)font.InnerFont; var size = gx.MeasureCharacterRanges( new string(buff, startAt, len), font2, System.Drawing.RectangleF.Empty, _stringFormat)[0].GetBounds(gx).Size; return(new PixelFarm.Drawing.Size((int)Math.Round(size.Width), (int)Math.Round(size.Height))); }
/// <summary> /// Measures the location of an arbritrary # of words within a string /// </summary> private WordStartFinish[] MeasureString(string s, System.Drawing.Graphics g, System.Drawing.Font drawFont, System.Drawing.StringFormat drawFormat, System.Drawing.CharacterRange[] cra) { if (cra.Length <= MEASUREMAX) // handle the simple case of < MEASUREMAX words { return(MeasureString32(s, g, drawFont, drawFormat, cra)); } // Need to compensate for SetMeasurableCharacterRanges limitation of 32 (MEASUREMAX) int mcra = (cra.Length / MEASUREMAX); // # of full 32 arrays we need int ip = cra.Length % MEASUREMAX; // # of partial entries needed for last array (if any) WordStartFinish[] sz = new WordStartFinish[cra.Length]; // this is the final result; float startPos = 0; System.Drawing.CharacterRange[] cra32 = new System.Drawing.CharacterRange[MEASUREMAX]; // fill out int icra = 0; // index thru the cra for (int i = 0; i < mcra; i++) { // fill out the new array int ticra = icra; for (int j = 0; j < cra32.Length; j++) { cra32[j] = cra[ticra++]; cra32[j].First -= cra[icra].First; // adjust relative offsets of strings } // measure the word locations (in the new string) // ???? should I put a blank in front of it?? string ts = s.Substring(cra[icra].First, cra[icra + cra32.Length - 1].First + cra[icra + cra32.Length - 1].Length - cra[icra].First); WordStartFinish[] pos = MeasureString32(ts, g, drawFont, drawFormat, cra32); // copy the values adding in the new starting positions for (int j = 0; j < pos.Length; j++) { sz[icra].start = pos[j].start + startPos; sz[icra++].end = pos[j].end + startPos; } startPos = sz[icra - 1].end; // reset the start position for the next line } // handle the remaining character if (ip > 0) { // resize the range array cra32 = new System.Drawing.CharacterRange[ip]; // fill out the new array int ticra = icra; for (int j = 0; j < cra32.Length; j++) { cra32[j] = cra[ticra++]; cra32[j].First -= cra[icra].First; // adjust relative offsets of strings } // measure the word locations (in the new string) // ???? should I put a blank in front of it?? string ts = s.Substring(cra[icra].First, cra[icra + cra32.Length - 1].First + cra[icra + cra32.Length - 1].Length - cra[icra].First); WordStartFinish[] pos = MeasureString32(ts, g, drawFont, drawFormat, cra32); // copy the values adding in the new starting positions for (int j = 0; j < pos.Length; j++) { sz[icra].start = pos[j].start + startPos; sz[icra++].end = pos[j].end + startPos; } } return(sz); }
private string[] MeasureString(PageText pt, System.Drawing.Graphics g, out float[] width) { StyleInfo si = pt.SI; string s = pt.Text; System.Drawing.Font drawFont = null; System.Drawing.StringFormat drawFormat = null; System.Drawing.SizeF ms; string[] sa = null; width = null; try { // STYLE System.Drawing.FontStyle fs = 0; if (si.FontStyle == FontStyleEnum.Italic) { fs |= System.Drawing.FontStyle.Italic; } // WEIGHT switch (si.FontWeight) { case FontWeightEnum.Bold: case FontWeightEnum.Bolder: case FontWeightEnum.W500: case FontWeightEnum.W600: case FontWeightEnum.W700: case FontWeightEnum.W800: case FontWeightEnum.W900: fs |= System.Drawing.FontStyle.Bold; break; default: break; } drawFont = new System.Drawing.Font(StyleInfo.GetFontFamily(si.FontFamilyFull), si.FontSize, fs); drawFormat = new System.Drawing.StringFormat(); drawFormat.Alignment = System.Drawing.StringAlignment.Near; // Measure string // pt.NoClip indicates that this was generated by PageTextHtml Build. It has already word wrapped. if (pt.NoClip || pt.SI.WritingMode == WritingModeEnum.tb_rl) // TODO: support multiple lines for vertical text { ms = MeasureString(s, g, drawFont, drawFormat); width = new float[1]; width[0] = RSize.PointsFromPixels(g, ms.Width); // convert to points from pixels sa = new string[1]; sa[0] = s; return(sa); } // handle multiple lines; // 1) split the string into the forced line breaks (ie "\n and \r") // 2) foreach of the forced line breaks; break these into words and recombine s = s.Replace("\r\n", "\n"); // don't want this to result in double lines string[] flines = s.Split(lineBreak); List <string> lines = new List <string>(); List <float> lineWidths = new List <float>(); // remove the size reserved for left and right padding float ptWidth = pt.W - pt.SI.PaddingLeft - pt.SI.PaddingRight; if (ptWidth <= 0) { ptWidth = 1; } foreach (string tfl in flines) { string fl; if (tfl.Length > 0 && tfl[tfl.Length - 1] == ' ') { fl = tfl.TrimEnd(' '); } else { fl = tfl; } // Check if entire string fits into a line ms = MeasureString(fl, g, drawFont, drawFormat); float tw = RSize.PointsFromPixels(g, ms.Width); if (tw <= ptWidth) { // line fits don't need to break it down further lines.Add(fl); lineWidths.Add(tw); continue; } // Line too long; need to break into multiple lines // 1) break line into parts; then build up again keeping track of word positions string[] parts = fl.Split(wordBreak); // this is the maximum split of lines StringBuilder sb = new StringBuilder(fl.Length); System.Drawing.CharacterRange[] cra = new System.Drawing.CharacterRange[parts.Length]; for (int i = 0; i < parts.Length; i++) { int sc = sb.Length; // starting character sb.Append(parts[i]); // endding character if (i != parts.Length - 1) // last item doesn't need blank { sb.Append(" "); } int ec = sb.Length; System.Drawing.CharacterRange cr = new System.Drawing.CharacterRange(sc, ec - sc); cra[i] = cr; // add to character array } // 2) Measure the word locations within the line string wfl = sb.ToString(); WordStartFinish[] wordLocations = MeasureString(wfl, g, drawFont, drawFormat, cra); if (wordLocations == null) { continue; } // 3) Loop thru creating new lines as needed int startLoc = 0; System.Drawing.CharacterRange crs = cra[startLoc]; System.Drawing.CharacterRange cre = cra[startLoc]; float cwidth = wordLocations[0].end; // length of the first float bwidth = wordLocations[0].start; // characters need a little extra on start string ts; bool bLine = true; for (int i = 1; i < cra.Length; i++) { cwidth = wordLocations[i].end - wordLocations[startLoc].start + bwidth; if (cwidth > ptWidth) { // time for a new line cre = cra[i - 1]; ts = wfl.Substring(crs.First, cre.First + cre.Length - crs.First); lines.Add(ts); lineWidths.Add(wordLocations[i - 1].end - wordLocations[startLoc].start + bwidth); // Find the first non-blank character of the next line while (i < cra.Length && cra[i].Length == 1 && fl[cra[i].First] == ' ') { i++; } if (i < cra.Length) // any lines left? { // yes, continue on startLoc = i; crs = cre = cra[startLoc]; cwidth = wordLocations[i].end - wordLocations[startLoc].start + bwidth; } else // no, we can stop { bLine = false; } // bwidth = wordLocations[startLoc].start - wordLocations[startLoc - 1].end; } else { cre = cra[i]; } } if (bLine) { ts = fl.Substring(crs.First, cre.First + cre.Length - crs.First); lines.Add(ts); lineWidths.Add(cwidth); } } // create the final array from the Lists string[] la = lines.ToArray(); width = lineWidths.ToArray(); return(la); } finally { if (drawFont != null) { drawFont.Dispose(); } if (drawFormat != null) { drawFont.Dispose(); } } }
private CharacterRange(System.Drawing.CharacterRange characterRange) { WrappedCharacterRange = characterRange; }