예제 #1
0
파일: Bitmap.cs 프로젝트: thomaswp/RTS
        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)));
        }
예제 #3
0
        /// <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);
        }
예제 #4
0
        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();
                }
            }
        }
예제 #5
0
 private CharacterRange(System.Drawing.CharacterRange characterRange)
 {
     WrappedCharacterRange = characterRange;
 }