/// <summary>
 /// Creates DwellOnIdentifierEventArgs instance with read-only values set
 /// </summary>
 /// <param name="identifier"></param>
 /// <param name="identifierRange"></param>
 /// <param name="visibleRange"></param>
 /// <param name="visibleText"></param>
 public DwellOnIdentifierEventArgs(string identifier, CharacterRange identifierRange, CharacterRange visibleRange, string visibleText)
 {
     Identifier = identifier;
     IdentifierRange = identifierRange;
     VisibleRange = visibleRange;
     VisibleText = visibleText;
 }
示例#2
0
        private static List <PatchSection> CombineSections(
            List <PatchSection> sections1, List <PatchSection> sections2,
            PatchSection exceptSection1, PatchSection exceptSection2,
            List <PatchVertex> vertices1, List <PatchVertex> vertices2,
            List <int> path1, List <int> path2,
            List <int> combinedPath,
            Dictionary <PointF, int> p2i)
        {
            List <PatchSection> sections = new List <PatchSection>();

            foreach (var sec in sections1)
            {
                if (sec == exceptSection1)
                {
                    continue;
                }

                // 切り口の端点が新しいメッシュ内でどこにあるか
                sections.Add(GetMappedSection(sec, vertices1, path1, combinedPath, p2i));
            }
            foreach (var sec in sections2)
            {
                if (sec == exceptSection2)
                {
                    continue;
                }

                // 切り口の端点が新しいメッシュ内でどこにあるか
                sections.Add(GetMappedSection(sec, vertices2, path2, combinedPath, p2i));
            }
            return(sections);
        }
示例#3
0
        static float SectionHeight(PatchSkeletalMesh mesh, PatchSection section, PatchSkeletonBone b)
        {
            List <PointF> path = GetPath(mesh).Select(v => v.position).ToList();

            var curves = SectionToAdjuscentCurves(path, section, 5, 30);

            if (path == null || curves == null || b == null)
            {
                return(0);
            }

            if (curves.Item1 == null || curves.Item2 == null)
            {
                return(0);
            }

            float height = 0;

            float boneLen = FMath.Distance(b.src.position, b.dst.position);

            if (boneLen <= 1e-4)
            {
                return(0);
            }

            PointF x, y;

            CalcBoneCoordinate(b, out x, out y);

            // 各セグメントのボーンからのズレを求める
            int cnt = Math.Min(curves.Item1.Length, curves.Item2.Length);

            for (int i = 0; i < cnt; i++)
            {
                int idx1 = curves.Item1.First + curves.Item1.Length - 1 - i;
                int idx2 = curves.Item2.First + i;
                while (idx1 < 0)
                {
                    idx1 += path.Count;
                }
                while (idx2 < 0)
                {
                    idx2 += path.Count;
                }
                PointF pt1 = path[idx1 % path.Count];
                PointF pt2 = path[idx2 % path.Count];
                pt1.X  -= b.src.position.X;
                pt1.Y  -= b.src.position.Y;
                pt2.X  -= b.src.position.X;
                pt2.Y  -= b.src.position.Y;
                height += pt1.X * y.X + pt1.Y * y.Y;
                height += pt2.X * y.X + pt2.Y * y.Y;
            }

            height /= 2 * cnt;

            return(height);
        }
示例#4
0
        /// <param name="checkLength">sectionから何pixel分の輪郭を計算に使うか/param>
        static float SectionHeight(PatchSkeletalMesh mesh, PatchSection section, PatchSkeletonBone b, float curveLength)
        {
            List <PatchVertex> path = GetPath(mesh);
            var rawcurves           = section2adjCurves(path, section);

            if (path == null || rawcurves == null || b == null)
            {
                return(0);
            }

            var curves = TrimCurves(path, rawcurves, 0, curveLength);

            if (curves.Item1 == null || curves.Item2 == null)
            {
                return(0);
            }

            float boneLen = FMath.Distance(b.src.position, b.dst.position);

            if (boneLen <= 1e-4)
            {
                return(0);
            }

            PointF x, y;

            BoneCoordinate(b, out x, out y);

            // 各セグメントのボーンからのズレを求める
            float height = 0;
            int   cnt    = Math.Min(curves.Item1.Length, curves.Item2.Length);

            for (int i = 0; i < cnt; i++)
            {
                int idx1 = curves.Item1.First + curves.Item1.Length - 1 - i;
                int idx2 = curves.Item2.First + i;
                while (idx1 < 0)
                {
                    idx1 += path.Count;
                }
                while (idx2 < 0)
                {
                    idx2 += path.Count;
                }
                PointF pt1 = path[idx1 % path.Count].position;
                PointF pt2 = path[idx2 % path.Count].position;
                pt1.X  -= b.src.position.X;
                pt1.Y  -= b.src.position.Y;
                pt2.X  -= b.src.position.X;
                pt2.Y  -= b.src.position.Y;
                height += pt1.X * y.X + pt1.Y * y.Y;
                height += pt2.X * y.X + pt2.Y * y.Y;
            }

            height /= 2 * cnt;

            return(height);
        }
示例#5
0
文件: Util.cs 项目: cmrazek/ProbeNpp
        public static SizeF MeasureString(Graphics g, string str, Font font, Rectangle rect, StringFormat sf)
        {
            var sfTemp = sf.Clone() as StringFormat;
            var ranges = new CharacterRange[] { new CharacterRange(0, str.Length) };
            sfTemp.SetMeasurableCharacterRanges(ranges);

            var regions = g.MeasureCharacterRanges(str, font, rect, sfTemp);
            if (regions != null && regions.Length > 0) return regions[0].GetBounds(g).Size;
            return new SizeF();
        }
            public Word(CharacterRange range, string text)
            {
                if (text == null)
                    throw new ArgumentNullException("text");

                Debug.Assert(text.Length > 0);

                _range = range;
                _text = text;
            }
        private int findCharacterPositionInPart(DocumentRow row, StylizedRowElement atom, float offset)
        {
            int farLength = atom.range.Length;
            int nearLength = 0;

            CharacterRange range = new CharacterRange(0, farLength);
            string test = row.Raw.Substring(range.First, range.Length);

            float nearSize = 0;
            float farSize = MeasureStringPart(range, test, atom.style).Size.Width;

            if (nearSize > offset) return nearLength;
            if (farSize < offset) return farLength - 1;

            while (farLength > nearLength)
            {
                if (farSize < offset)
                {
                    break;
                }

                if (nearSize > offset)
                {
                    farLength = nearLength;
                    break;
                }

                range = new CharacterRange(0, nearLength + (farLength - nearLength) / 2);
                test = row.Raw.Substring(range.First, range.Length);
                float middle = MeasureStringPart(range, test, atom.style).Size.Width;

                if (middle < offset)
                {
                    if (nearLength == range.Length)
                    {
                        return farSize - middle > middle - nearSize ? nearLength : farLength;
                    }

                    nearLength = range.Length;
                    nearSize = middle;
                }
                else
                {
                    if (farLength == range.Length)
                    {
                        return farSize - middle > middle - nearSize ? nearLength : farLength;
                    }

                    farLength = range.Length;
                    farSize = middle;
                }
            }

            return farLength;
        }
        private EMFStringFormat(byte[] RecordData)
        {
            ObjectType     = EmfObjectType.stringformat;
            myStringFormat = new System.Drawing.StringFormat();
            //put the Data into a stream and use a binary reader to read the data
            MemoryStream _ms = new MemoryStream(RecordData);
            BinaryReader _br = new BinaryReader(_ms);

            _br.ReadUInt32(); //Who cares about version..not me!
            myStringFormat.FormatFlags = (StringFormatFlags)_br.ReadUInt32();
            _br.ReadBytes(4); //Language...Ignore for now!
            myStringFormat.LineAlignment = (StringAlignment)_br.ReadUInt32();
            myStringFormat.Alignment     = (StringAlignment)_br.ReadUInt32();
            UInt32 DigitSubstitutionMethod   = _br.ReadUInt32();
            UInt32 DigitSubstitutionLanguage = _br.ReadUInt32();

            myStringFormat.SetDigitSubstitution((int)DigitSubstitutionLanguage, (StringDigitSubstitute)DigitSubstitutionMethod);

            Single FirstTabOffSet = _br.ReadSingle();

            myStringFormat.HotkeyPrefix = (System.Drawing.Text.HotkeyPrefix)_br.ReadInt32();

            _br.ReadSingle(); //leading Margin
            _br.ReadSingle(); //trailingMargin
            _br.ReadSingle(); //tracking
            myStringFormat.Trimming = (StringTrimming)_br.ReadUInt32();
            Int32 TabStopCount = _br.ReadInt32();
            Int32 RangeCount   = _br.ReadInt32();

            //Next is stringformatdata...
            Single[] TabStopArray;
            System.Drawing.CharacterRange[] RangeArray;

            if (TabStopCount > 0)
            {
                TabStopArray = new Single[TabStopCount];
                for (int i = 0; i < TabStopCount; i++)
                {
                    TabStopArray[i] = _br.ReadSingle();
                }
                myStringFormat.SetTabStops(FirstTabOffSet, TabStopArray);
            }

            if (RangeCount > 0)
            {
                RangeArray = new System.Drawing.CharacterRange[RangeCount];
                for (int i = 0; i < RangeCount; i++)
                {
                    RangeArray[i].First  = _br.ReadInt32();
                    RangeArray[i].Length = _br.ReadInt32();
                }
                myStringFormat.SetMeasurableCharacterRanges(RangeArray);
            }
        }
示例#9
0
 private static SizeF GetTextSize(string str, Graphics g, bool fTitle) {
     SizeF empty = SizeF.Empty;
     CharacterRange[] ranges = new CharacterRange[] { new CharacterRange(0, str.Length) };
     sfMeasure.SetMeasurableCharacterRanges(ranges);
     Region[] regionArray = g.MeasureCharacterRanges(str, fTitle ? font : fontSubText, rctMeasure, sfMeasure);
     using(regionArray[0]) {
         empty = regionArray[0].GetBounds(g).Size;
         empty.Width += 6f;
     }
     return empty;
 }
示例#10
0
        //-----------------------------------------------------------------------------------
        // FindConnectingSections()
        //-----------------------------------------------------------------------------------

        /// <summary>
        /// skl内の同一のボーンと交差していて、なおかつ向きが逆の切り口を探す
        /// </summary>
        private static bool FindConnectingSections(
            PatchSkeletalMesh smesh1, PatchSkeletalMesh smesh2, PatchSkeleton skl,
            out PatchSection section1, out PatchSection section2, out PatchSkeletonBone crossingBone)
        {
            section1     = new PatchSection(0, -1);
            section2     = new PatchSection(0, -1);
            crossingBone = null;

            if (skl == null)
            {
                return(false);
            }

            if (smesh1 == null || smesh2 == null)
            {
                return(false);
            }

            foreach (var bone in skl.bones)
            {
                List <PatchSection> sections1, sections2;
                List <float>        dir1, dir2;

                // 各切り口がboneと交差しているか
                if (!FindCrossingSection(smesh1, bone, out sections1, out dir1))
                {
                    continue;
                }
                if (!FindCrossingSection(smesh2, bone, out sections2, out dir2))
                {
                    continue;
                }

                for (int i = 0; i < sections1.Count; i++)
                {
                    for (int j = 0; j < sections2.Count; j++)
                    {
                        // 2つの切り口が逆向きか
                        if (dir1[i] * dir2[j] >= 0)
                        {
                            continue;
                        }
                        section1     = sections1[i];
                        section2     = sections2[j];
                        crossingBone = bone;
                        return(true);
                    }
                }
            }

            return(false);
        }
        private EMFStringFormat(byte[] RecordData)        
        {
            ObjectType = EmfObjectType.stringformat;
            myStringFormat = new System.Drawing.StringFormat();
            //put the Data into a stream and use a binary reader to read the data
            MemoryStream _ms = new MemoryStream(RecordData);
            BinaryReader _br = new BinaryReader(_ms);           
            _br.ReadUInt32(); //Who cares about version..not me!            
            myStringFormat.FormatFlags = (StringFormatFlags)_br.ReadUInt32();
            _br.ReadBytes(4);//Language...Ignore for now!
            myStringFormat.LineAlignment = (StringAlignment)_br.ReadUInt32();
            myStringFormat.Alignment = (StringAlignment)_br.ReadUInt32();
            UInt32 DigitSubstitutionMethod = _br.ReadUInt32();
            UInt32 DigitSubstitutionLanguage = _br.ReadUInt32();
            myStringFormat.SetDigitSubstitution((int)DigitSubstitutionLanguage, (StringDigitSubstitute)DigitSubstitutionMethod);
            
            Single FirstTabOffSet = _br.ReadSingle();

            myStringFormat.HotkeyPrefix = (System.Drawing.Text.HotkeyPrefix) _br.ReadInt32();

             _br.ReadSingle();//leading Margin
             _br.ReadSingle();//trailingMargin           
             _br.ReadSingle();//tracking
            myStringFormat.Trimming = (StringTrimming)_br.ReadUInt32();           
            Int32 TabStopCount = _br.ReadInt32();
            Int32 RangeCount = _br.ReadInt32();
            //Next is stringformatdata...
            Single[] TabStopArray;           
            System.Drawing.CharacterRange[] RangeArray;

            if (TabStopCount > 0)
            {
                TabStopArray = new Single[TabStopCount];
                for (int i = 0; i < TabStopCount; i++)
                {
                    TabStopArray[i] = _br.ReadSingle();
                }
                myStringFormat.SetTabStops(FirstTabOffSet, TabStopArray);
            }

            if (RangeCount > 0)
            {
                RangeArray = new System.Drawing.CharacterRange[RangeCount];
                for (int i = 0; i < RangeCount; i++)
                {
                    RangeArray[i].First = _br.ReadInt32();
                    RangeArray[i].Length = _br.ReadInt32();
                }
                myStringFormat.SetMeasurableCharacterRanges(RangeArray);
            }
        }
示例#12
0
文件: TextUtil.cs 项目: NanQi/demo
 public static Size GetTextSize(Graphics graphics, string text, Font font, Size size)
 {
    if (text.Length == 0)
    {
       return Size.Empty;
    }
    StringFormat stringFormat = new StringFormat();
    stringFormat.FormatFlags = StringFormatFlags.FitBlackBox;
    RectangleF layoutRect = new RectangleF(0f, 0f, size.Width, size.Height);
    CharacterRange[] ranges = new CharacterRange[] {new CharacterRange(0, text.Length)};
    Region[] regionArray = new Region[1];
    stringFormat.SetMeasurableCharacterRanges(ranges);
    Rectangle rectangle =
       Rectangle.Round(graphics.MeasureCharacterRanges(text, font, layoutRect, stringFormat)[0].GetBounds(graphics));
    return new Size(rectangle.Width, rectangle.Height);
 }
示例#13
0
        public float[] GetCharacterXPositions( Graphics g, string str )
        {
            // Setup the StringFormat with proper CharacterRange references.
            StringFormat testFormat = new StringFormat();
            CharacterRange[] ranges = new CharacterRange[ str.Length ];
            for ( int i=0; i < str.Length; i++ )
                ranges[i] = new CharacterRange( i, 1 );

            testFormat.SetMeasurableCharacterRanges( ranges );

            // Measure into Regions
            Region[] regions = g.MeasureCharacterRanges( str, _font, new Rectangle( 0, 0, 1000, 1000 ), testFormat );

            // Convert Regions to Rects, then X coords.
            float[] xCoords = regions.Select( region => region.GetBounds( g ).X ).ToArray();
            return xCoords;
        }
示例#14
0
        //
        // AdjustPosition()
        //

        static void AdjustPosition(
            PatchSkeletalMesh smesh1, PatchSkeletalMesh smesh2, PatchSkeleton skl,
            PatchSection section1, PatchSection section2, PatchSkeletonBone bone)
        {
            PatchSkeletonBone refBone = null;

            foreach (var b in skl.bones)
            {
                if (bone == b)
                {
                    refBone = b;
                    break;
                }
            }

            if (refBone == null)
            {
                return;
            }

            // 切り口の中心とボーンの軸とのずれ(ボーンと垂直な方向について)
            float height1 = SectionHeight(smesh1, section1, refBone);
            float height2 = SectionHeight(smesh2, section2, refBone);

            // ボーンと水平なベクトルと垂直なベクトルをそれぞれx, yとして取得
            PointF x, y;

            CalcBoneCoordinate(refBone, out x, out y);

            // smesh2の切り口の中心がsmesh1の切り口の中心に重なるようにsmesh2をずらす
            if (Math.Abs(height1 - height2) > 1e-4)
            {
                float dx = y.X * (height1 - height2);
                float dy = y.Y * (height1 - height2);

                // mesh2の頂点・制御点を平行移動する
                foreach (var v in smesh2.mesh.vertices)
                {
                    v.position = new PointF(v.position.X + dx, v.position.Y + dy);
                }
                foreach (var c in smesh2.mesh.CopyControlPoints())
                {
                    smesh2.mesh.TranslateControlPoint(c.position, new PointF(c.position.X + dx, c.position.Y + dy), false);
                }
            }
        }
示例#15
0
        static PatchSection GetMappedSection(PatchSection orgsection, List <PatchVertex> vertices, List <int> orgpath, List <int> combinedPath, Dictionary <PointF, int> p2i)
        {
            int    idx0    = orgpath[FMath.Rem(orgsection.First, orgpath.Count)];
            PointF p0      = vertices[idx0].position;
            int    newIdx0 = combinedPath.IndexOf(p2i[p0]);

            int    idx1    = orgpath[FMath.Rem(orgsection.First + orgsection.Length - 1, orgpath.Count)];
            PointF p1      = vertices[idx1].position;
            int    newIdx1 = combinedPath.IndexOf(p2i[p1]);

            if (newIdx0 > newIdx1)
            {
                FMath.Swap(ref newIdx0, ref newIdx1);
            }

            PatchSection newSection = new PatchSection(newIdx0, newIdx1 - newIdx0 + 1);

            return(newSection);
        }
示例#16
0
 private static int getDrawLength(Graphics g, Font fnt, RectangleF rect, StringFormat sf, int maxLen)
 {
     CharacterRange[] ranges = new CharacterRange[] { new CharacterRange(0, 1) };
     float num = 1f;
     float width = 0f;
     int num3 = 2;
     string text = StrFunc.CreateInstance().MakeCycleStr(maxLen, "X");
     while ((num3 <= maxLen) && (width != num))
     {
         num = width;
         ranges[0].Length = num3;
         sf.SetMeasurableCharacterRanges(ranges);
         width = g.MeasureCharacterRanges(text, fnt, rect, sf)[0].GetBounds(g).Width;
         num3++;
     }
     if (num3 == maxLen)
     {
         return maxLen;
     }
     return (num3 - 1);
 }
示例#17
0
		public void MeasureCharacterRanges_StringFormat_LineAlignment_DirectionVertical ()
		{
			if (font == null)
				Assert.Ignore ("Couldn't create required font");

			string text = "Hello Mono::";
			CharacterRange[] ranges = new CharacterRange[1];
			ranges[0] = new CharacterRange (5, 4);
			StringFormat string_format = new StringFormat ();
			string_format.FormatFlags = StringFormatFlags.DirectionVertical;
			string_format.SetMeasurableCharacterRanges (ranges);

			using (Bitmap bitmap = new Bitmap (20, 20)) {
				using (Graphics g = Graphics.FromImage (bitmap)) {
					string_format.LineAlignment = StringAlignment.Near;
					Region[] regions = g.MeasureCharacterRanges (text, font, new RectangleF (0, 0, 320, 32), string_format);
					Assert.AreEqual (1, regions.Length, "Near.Region");
					RectangleF near = regions[0].GetBounds (g);

					string_format.LineAlignment = StringAlignment.Center;
					regions = g.MeasureCharacterRanges (text, font, new RectangleF (0, 0, 320, 32), string_format);
					Assert.AreEqual (1, regions.Length, "Center.Region");
					RectangleF center = regions[0].GetBounds (g);

					string_format.LineAlignment = StringAlignment.Far;
					regions = g.MeasureCharacterRanges (text, font, new RectangleF (0, 0, 320, 32), string_format);
					Assert.AreEqual (1, regions.Length, "Far.Region");
					RectangleF far = regions[0].GetBounds (g);

					Assert.IsTrue (near.X < center.X, "near-center/X");
					Assert.AreEqual (near.Y, center.Y, 0.1, "near-center/Y");
					Assert.AreEqual (near.Width, center.Width, 0.1, "near-center/Width");
					Assert.AreEqual (near.Height, center.Height, 0.1, "near-center/Height");

					Assert.IsTrue (center.X < far.X, "center-far/X");
					Assert.AreEqual (center.Y, far.Y, 0.1, "center-far/Y");
					Assert.AreEqual (center.Width, far.Width, 0.1, "center-far/Width");
					Assert.AreEqual (center.Height, far.Height, 0.1, "center-far/Height");
				}
			}
		}
示例#18
0
		private void MeasureCharacterRanges (string text, int first, int length)
		{
			if (font == null)
				Assert.Ignore ("Couldn't create required font");

			CharacterRange[] ranges = new CharacterRange[1];
			ranges[0] = new CharacterRange (first, length);

			StringFormat string_format = new StringFormat ();
			string_format.FormatFlags = StringFormatFlags.NoClip;
			string_format.SetMeasurableCharacterRanges (ranges);

			using (Bitmap bitmap = new Bitmap (20, 20)) {
				using (Graphics g = Graphics.FromImage (bitmap)) {
					SizeF size = g.MeasureString (text, font, new Point (0, 0), string_format);
					RectangleF layout_rect = new RectangleF (0.0f, 0.0f, size.Width, size.Height);
					g.MeasureCharacterRanges (text, font, layout_rect, string_format);
				}
			}
		}
		public Region[] MeasureStringLine(Graphics g, string text, CharacterRange[] measureRanges, Font font, Rectangle textRect, StringAlignment align = StringAlignment.Near, StringAlignment lineAlign = StringAlignment.Center)
		{
			// Expand text rect, because DrawString stops too soon
			textRect.Width += DrawStringWidthAdd;
			textRect.Height = Math.Max(textRect.Height, font.Height);

			// Assume manual ellipsis
			textRect.Width -= 5;
			StringFormat nameLabelFormat = StringFormat.GenericDefault;
			nameLabelFormat.Alignment = align;
			nameLabelFormat.LineAlignment = lineAlign;
			nameLabelFormat.Trimming = StringTrimming.Character;
			nameLabelFormat.FormatFlags |= StringFormatFlags.NoWrap | StringFormatFlags.MeasureTrailingSpaces;
			nameLabelFormat.SetMeasurableCharacterRanges(measureRanges);

			return g.MeasureCharacterRanges(text, font, textRect, nameLabelFormat);
		}
示例#20
0
 public FaceApplied(string face, CharacterRange range)
 {
     this.face = face;
     this.range = range;
 }
示例#21
0
        //-----------------------------------------------------------------------------------
        // Deform()
        //-----------------------------------------------------------------------------------

        /// <summary>
        /// 切り口付近で2つのsmeshが重なるように変形する
        /// </summary>
        private static void Deform(PatchSkeletalMesh smesh1, PatchSkeletalMesh smesh2, PatchSkeleton skl, PatchSection section1, PatchSection section2, PatchSkeletonBone crossingBone)
        {
            if (smesh1 == null || smesh2 == null)
            {
                return;
            }

            // 各メッシュを大雑把にスケルトンに合わせる
            PatchSkeletonFitting.Fitting(smesh1, skl);
            PatchSkeletonFitting.Fitting(smesh2, skl);
#if _DEBUG
            PatchSkeletalMeshRenderer.ToBitmap(smesh1, new List <PatchSection>()
            {
                section1
            }).Save("output/5_1_mesh1_fitting.png");
            PatchSkeletalMeshRenderer.ToBitmap(smesh2, new List <PatchSection>()
            {
                section2
            }).Save("output/5_2_mesh2_fitting.png");
#endif

            // サイズの修正は手動でやる
            // 回転はFitting()でやってるから必要ない

            // 位置の調整
            AdjustPosition(smesh1, smesh2, skl, section1, section2, crossingBone);
#if _DEBUG
            PatchSkeletalMeshRenderer.ToBitmap(smesh1, new List <PatchSection>()
            {
                section1
            }).Save("output/5_3_mesh1_AdjustPosition.png");
            PatchSkeletalMeshRenderer.ToBitmap(smesh2, new List <PatchSection>()
            {
                section2
            }).Save("output/5_4_mesh2_AdjustPosition.png");
#endif

            // メッシュを伸ばして繋げる
            Expand(smesh1, smesh2, skl, section1, section2, crossingBone);
#if _DEBUG
            PatchSkeletalMeshRenderer.ToBitmap(smesh1, new List <PatchSection>()
            {
                section1
            }).Save("output/5_5_mesh1_ExpandPatches.png");
            PatchSkeletalMeshRenderer.ToBitmap(smesh2, new List <PatchSection>()
            {
                section2
            }).Save("output/5_6_mesh2_ExpandPatches.png");
#endif
        }
示例#22
0
        private static List <int> CombinePath(List <int> path1, List <int> path2,
                                              List <PatchVertex> vertices1,
                                              List <PatchVertex> vertices2,
                                              PatchSection section1, PatchSection section2,
                                              Dictionary <PointF, int> p2i)
        {
            List <int> path = new List <int>();

            HashSet <int> sectionIndices1 = new HashSet <int>();

            for (int i = section1.First; i < section1.First + section1.Length; i++)
            {
                sectionIndices1.Add(i);
            }

            HashSet <int> sectionIndices2 = new HashSet <int>();

            for (int i = section2.First; i < section2.First + section2.Length; i++)
            {
                sectionIndices2.Add(i);
            }

            HashSet <PointF> pathPoints = new HashSet <PointF>();

            // 切り口の端からパスを登録していく.  切り口の両端は必ずpathに含まれている。と思う
            for (int _i = section1.First + section1.Length; _i != section1.First + 1; _i = FMath.Rem(_i + 1, path1.Count))
            {
                int i = path1[_i];
                if (sectionIndices1.Contains(i))
                {
                    continue;
                }
                path.Add(p2i[vertices1[i].position]);
                pathPoints.Add(vertices1[i].position);
            }

            PointF path1_preendPt = vertices1[path1[FMath.Rem(section1.First - 1, path1.Count)]].position;
            PointF path1_endPt    = vertices1[path1[FMath.Rem(section1.First, path1.Count)]].position;

            int path2_start = -1;

            for (int i = 0; i < path2.Count; i++)
            {
                if (vertices2[path2[i]].position == path1_endPt)
                {
                    path2_start = i;
                    break;
                }
            }

            if (path2_start < 0)
            {
                return(new List <int>());
            }

            int    path2_poststart   = FMath.Rem(path2_start + 1, path2.Count);
            PointF path2_poststartPt = vertices2[path2[path2_poststart]].position;
            int    dir = 1;

            if (path2_poststartPt == path1_preendPt)
            {
                dir = -1;
            }

            for (int i = path2_start + dir; ; i += dir)
            {
                PointF pt = vertices2[path2[FMath.Rem(i, path2.Count)]].position;
                if (path.Contains(p2i[pt]))
                {
                    break;
                }
                path.Add(p2i[pt]);
            }

            return(path);
        }
示例#23
0
		public void StringFormat ()
		{
			IntPtr sf;
			Assert.AreEqual (Status.Ok, GDIPlus.GdipCreateStringFormat (Int32.MinValue, Int32.MinValue, out sf), "GdipCreateStringFormat");

			CheckStringFormat (sf, (StringFormatFlags) Int32.MinValue, StringTrimming.Character);

			CharacterRange[] ranges = new CharacterRange[32];
			Assert.AreEqual (Status.InvalidParameter, GDIPlus.GdipSetStringFormatMeasurableCharacterRanges (IntPtr.Zero, 1, ranges), "GdipSetStringFormatMeasurableCharacterRanges-null");
			Assert.AreEqual (Status.InvalidParameter, GDIPlus.GdipSetStringFormatMeasurableCharacterRanges (IntPtr.Zero, -1, ranges), "GdipSetStringFormatMeasurableCharacterRanges-negative");
			Assert.AreEqual (Status.Ok, GDIPlus.GdipSetStringFormatMeasurableCharacterRanges (sf, 1, ranges), "GdipSetStringFormatMeasurableCharacterRanges");
			Assert.AreEqual (Status.Ok, GDIPlus.GdipSetStringFormatMeasurableCharacterRanges (sf, 32, ranges), "GdipSetStringFormatMeasurableCharacterRanges-32");
			Assert.AreEqual (Status.ValueOverflow, GDIPlus.GdipSetStringFormatMeasurableCharacterRanges (sf, 33, ranges), "GdipSetStringFormatMeasurableCharacterRanges-33");

			float first = Single.MinValue;
			float[] tabs = new float[1];
			Assert.AreEqual (Status.InvalidParameter, GDIPlus.GdipSetStringFormatTabStops (IntPtr.Zero, 1.0f, 1, tabs), "GdipSetStringFormatTabStops-null");
			Assert.AreEqual (Status.InvalidParameter, GDIPlus.GdipSetStringFormatTabStops (sf, 1.0f, 1, null), "GdipSetStringFormatTabStops-null/tabs");
			
			Assert.AreEqual (Status.Ok, GDIPlus.GdipSetStringFormatTabStops (sf, 1.0f, -1, tabs), "GdipSetStringFormatTabStops-negative");
			Assert.AreEqual (Status.Ok, GDIPlus.GdipGetStringFormatTabStops (sf, 1, out first, tabs), "GdipGetStringFormatTabStops-negative");
			Assert.AreEqual (0.0f, first, "first-negative");

			Assert.AreEqual (Status.Ok, GDIPlus.GdipSetStringFormatTabStops (sf, 1.0f, 1, tabs), "GdipSetStringFormatTabStops");
			Assert.AreEqual (Status.Ok, GDIPlus.GdipGetStringFormatTabStops (sf, 1, out first, tabs), "GdipGetStringFormatTabStops");
			Assert.AreEqual (1.0f, first, "first");

			Assert.AreEqual (Status.InvalidParameter, GDIPlus.GdipDeleteStringFormat (IntPtr.Zero), "GdipDeleteStringFormat-null");
			Assert.AreEqual (Status.Ok, GDIPlus.GdipDeleteStringFormat (sf), "GdipDeleteStringFormat");
		}
示例#24
0
        //--------------------------------------------------------------------------
        // Combine()
        //--------------------------------------------------------------------------

        /// <summary>
        /// 2つのメッシュを統合して1つのARAP可能なメッシュを作成する
        /// TODO: さすがに関数にわけるべき
        /// </summary>
        static PatchSkeletalMesh Combine(PatchSkeletalMesh smesh1, PatchSkeletalMesh smesh2, PatchSection section1, PatchSection section2)
        {
            //
            // Meshを作成
            //

            List <PatchVertex> vertices = CombineVertices(smesh1.mesh.vertices, smesh2.mesh.vertices);

            // 頂点から各種インデックスへの辞書を作っておく
            Dictionary <PointF, int> p2i = new Dictionary <PointF, int>();

            for (int i = 0; i < vertices.Count; i++)
            {
                p2i[vertices[i].position] = i;
            }
            Dictionary <PointF, int> pt2part = vertices.ToDictionary(v => v.position, v => v.part);

            Dictionary <int, int> part2part_1 = new Dictionary <int, int>(); // smesh1の各パートが新しいメッシュのどのパートになるか

            foreach (var v in smesh1.mesh.vertices)
            {
                part2part_1[v.part] = pt2part[v.position];
            }

            Dictionary <int, int> part2part_2 = new Dictionary <int, int>(); // smesh2の各パートが新しいメッシュのどのパートになるか

            foreach (var v in smesh2.mesh.vertices)
            {
                part2part_2[v.part] = pt2part[v.position];
            }

            List <PatchControlPoint> controlPoints = CombineControlPoints(smesh1.mesh.CopyControlPoints(), smesh2.mesh.CopyControlPoints(), part2part_1, part2part_2);
            List <PatchTriangle>     triangles     = CombineTriangles(smesh1.mesh.triangles, smesh2.mesh.triangles, smesh1.mesh.vertices, smesh2.mesh.vertices, p2i);
            List <int> path = CombinePath(smesh1.mesh.pathIndices, smesh2.mesh.pathIndices, smesh1.mesh.vertices, smesh2.mesh.vertices, section1, section2, p2i);

            PatchMesh rawMesh = new PatchMesh(vertices, controlPoints, triangles, path);

            //
            // 骨格を統合
            //

            PatchSkeleton skl = CombineSkeleton(smesh1.skl, smesh2.skl);


            //
            // 切り口を統合.
            //
            List <PatchSection> sections = CombineSections(
                smesh1.sections, smesh2.sections,
                section1, section2,
                smesh1.mesh.vertices, smesh2.mesh.vertices,
                smesh1.Mesh.pathIndices, smesh2.Mesh.pathIndices,
                path, p2i);

            //
            // SkeletalMeshを作成.
            //
            PatchSkeletalMesh newMesh = new PatchSkeletalMesh(rawMesh, skl, sections);

            return(newMesh);
        }
示例#25
0
        // 切り口に隣接する部分パス(2つ)を返す
        // この部分を引き伸ばしてメッシュを繋げる
        static Tuple <CharacterRange, CharacterRange> SectionToAdjuscentCurves(List <PointF> path, PatchSection section, int maxPtNum, float maxAngle)
        {
            if (section.Length <= 0 || path == null || path.Count < 5 || maxPtNum < 3)
            {
                return(null);
            }

            float cos = (float)Math.Cos(maxAngle);

            // 1つ目の部分パス

            int start1 = section.First;

            while (start1 < 0)
            {
                start1 += path.Count;
            }
            start1 = start1 % path.Count;

            int end1 = start1 - 2;

            for (int i = 0; i < maxPtNum - 2; i++)
            {
                int idx   = (start1 - 2 - i + path.Count) % path.Count;
                var curve = new List <PointF>();
                for (int j = idx; j < idx + 3; j++)
                {
                    curve.Add(path[FMath.Rem(j, path.Count)]);
                }
                if (FMath.GetAngleCos(curve) < cos)
                {
                    break;
                }
                end1 = idx;
            }

            CharacterRange r1 = new CharacterRange();

            if (start1 > end1)
            {
                r1 = new CharacterRange(end1, start1 - end1 + 1);
            }
            if (start1 < end1)
            {
                // 始点と終点をまたがっている場合
                r1 = new CharacterRange(end1, start1 + path.Count - end1 + 1);
            }

            if (r1.Length <= 0)
            {
                return(null);
            }

            // 2つ目の部分パス

            int start2 = section.First + section.Length - 1;

            while (start2 < 0)
            {
                start2 += path.Count;
            }
            start2 = start2 % path.Count;

            int end2 = start2 + 2;

            for (int i = 0; i < maxPtNum - 2; i++)
            {
                int idx   = (start2 + i) % path.Count;
                var curve = path.Skip(idx).Take(3).ToList();
                if (FMath.GetAngleCos(curve) < cos)
                {
                    break;
                }
                end2 = start2 + i + 2;
            }

            CharacterRange r2 = new CharacterRange();

            if (start2 < end2)
            {
                r2 = new CharacterRange(start2, end2 - start2 + 1);
            }
            if (start2 > end2)
            {
                r2 = new CharacterRange(start2, end2 + path.Count - start2 + 1);
            }

            if (r2.Length <= 0)
            {
                return(null);
            }

            return(new Tuple <CharacterRange, CharacterRange>(r1, r2));
        }
示例#26
0
        //
        // Expand()
        //

        /// <summary>
        /// smesh1, smesh2の輪郭をずらして重ねる。輪郭に制御点をおいてARAPする
        /// </summary>
        static void Expand(PatchSkeletalMesh smesh1, PatchSkeletalMesh smesh2, PatchSkeleton skl, PatchSection section1, PatchSection section2, PatchSkeletonBone bone)
        {
            List <PatchVertex> rawPath1 = GetPath(smesh1);
            List <PatchVertex> rawPath2 = GetPath(smesh2);
            List <PointF>      path1    = rawPath1.Select(v => v.position).ToList();
            List <PointF>      path2    = rawPath2.Select(v => v.position).ToList();

            //
            // 輪郭を変形できるように制御点を作り直す
            //

            // smesh1
            smesh1.mesh.ClearControlPoints();
            foreach (var v in rawPath1)
            {
                smesh1.mesh.AddControlPoint(v.position, v.orgPosition);
            }
            smesh1.mesh.BeginDeformation();

            // smesh2
            smesh2.mesh.ClearControlPoints();
            foreach (var v in rawPath2)
            {
                smesh2.mesh.AddControlPoint(v.position, v.orgPosition);
            }
            smesh2.mesh.BeginDeformation();


            //
            // 切り口に隣接する2曲線を各切り口について取得し、これらが重なるように輪郭をずらす
            //

            // 切り口に隣接する2曲線をそれぞれ取得
            var rawCurves1 = SectionToAdjuscentCurves(path1, section1, 5, 30);
            var rawCurves2 = SectionToAdjuscentCurves(path2, section2, 5, 30);

            if (rawCurves1 == null || rawCurves2 == null)
            {
                return;
            }

            PatchSkeletonBone refBone = null;

            foreach (var b in skl.bones)
            {
                if (bone == b)
                {
                    refBone = b;
                    break;
                }
            }

            // curves1, curves2の第一要素、第二要素がそれぞれ向かい合う(ボーンにとって同じ側の)切り口となるように並び替える
            var curves1 = GetSortedCurves(path1, rawCurves1, refBone);
            var curves2 = GetSortedCurves(path2, rawCurves2, refBone);

            if (curves1.Count != 2 || curves2.Count != 2)
            {
                return;
            }

            // curves1, curves2の移動履歴を記録
            List <Tuple <PointF, PointF> > move1 = new List <Tuple <PointF, PointF> >();
            List <Tuple <PointF, PointF> > move2 = new List <Tuple <PointF, PointF> >();

            // 対応する曲線間で2点がかぶる(同じ座標になる)ように変形。
            for (int i = 0; i < 2; i++)
            {
                var p1 = curves1[i].First();
                var v1 = new PointF(p1.X - curves1[i].Last().X, p1.Y - curves1[i].Last().Y);
                var p2 = curves2[i].First();
                var v2 = new PointF(curves2[i].Last().X - p2.X, curves2[i].Last().Y - p2.Y);

                // 2点かぶらせる
                int cnt = curves1[i].Count + curves2[i].Count - 2;
                if (cnt <= 1)
                {
                    continue;
                }

                for (int j = 0; j < curves1[i].Count; j++)
                {
                    PointF to = FMath.HelmitteInterporate(p1, v1, p2, v2, (float)j / (cnt - 1));
                    if (j == curves1[i].Count - 1)
                    {
                        move1.Add(new Tuple <PointF, PointF>(curves1[i][j], to));
                    }
                    smesh1.mesh.TranslateControlPoint(curves1[i][j], to, false);
                }
                for (int j = 0; j < curves2[i].Count; j++)
                {
                    PointF to = FMath.HelmitteInterporate(p1, v1, p2, v2, (float)(-j + cnt - 1) / (cnt - 1));
                    if (j == curves2[i].Count - 1)
                    {
                        move2.Add(new Tuple <PointF, PointF>(curves2[i][j], to));
                    }
                    smesh2.mesh.TranslateControlPoint(curves2[i][j], to, false);
                }
            }

            //
            // 各曲線の動きに合わせて切り口を動かす
            //
            List <PointF> sections1 = new List <PointF>();

            for (int i = section1.First + 1; i < section1.First + section1.Length - 1; i++)
            {
                sections1.Add(path1[FMath.Rem(i, path1.Count)]);
            }
            List <PointF> newSection1 = ARAPDeformation.ARAPDeformation.Deform(sections1, move1);

            if (newSection1.Count == sections1.Count)
            {
                for (int i = 0; i < newSection1.Count; i++)
                {
                    smesh1.mesh.TranslateControlPoint(sections1[i], newSection1[i], false);
                }
            }

            List <PointF> sections2 = new List <PointF>();

            for (int i = section2.First + 1; i < section2.First + section2.Length - 1; i++)
            {
                sections2.Add(path2[FMath.Rem(i, path2.Count)]);
            }
            List <PointF> newSection2 = ARAPDeformation.ARAPDeformation.Deform(sections2, move2);

            if (newSection2.Count == sections2.Count)
            {
                for (int i = 0; i < newSection2.Count; i++)
                {
                    smesh2.mesh.TranslateControlPoint(sections2[i], newSection2[i], false);
                }
            }

            //
            // 変形
            //
            smesh1.mesh.FlushDefomation();
            smesh2.mesh.FlushDefomation();

            //
            // 変形終了
            //
            smesh1.mesh.EndDeformation();
            smesh2.mesh.EndDeformation();
        }
示例#27
0
        // ボーンのdst方向にあるのがpatch2
        static void OverlayPatches(PatchSkeletalMesh patch1, PatchSkeletalMesh patch2, PatchSkeleton refSkeleton, PatchSection section1, PatchSection section2, PatchSkeletonBone bone, float border)
        {
            PatchSkeletonBone refBone = RefBone(refSkeleton, bone);
            float             min1    = float.MaxValue;
            float             max2    = float.MinValue;

            List <PatchVertex> path1 = GetPath(patch1);
            List <PatchVertex> path2 = GetPath(patch2);

            for (int i = section1.First; i < section1.First + section1.Length; i++)
            {
                var   pt    = path1[FMath.Rem(i, path1.Count)].position;
                float param = FMath.ParameterOnLine(pt, refBone.src.position, refBone.dst.position);
                if (float.IsNaN(param))
                {
                    continue;
                }
                min1 = Math.Min(min1, param);
            }
            for (int i = section2.First; i < section2.First + section2.Length; i++)
            {
                var   pt    = path2[FMath.Rem(i, path2.Count)].position;
                float param = FMath.ParameterOnLine(pt, refBone.src.position, refBone.dst.position);
                if (float.IsNaN(param))
                {
                    continue;
                }
                max2 = Math.Max(max2, param);
            }

            PointF x, y;

            BoneCoordinate(refBone, out x, out y);

            float boneLength = FMath.Distance(refBone.src.position, refBone.dst.position);
            float dparam     = border / boneLength;
            float delta      = (min1 - max2 - dparam) * boneLength;
            float dx         = x.X * delta;
            float dy         = x.Y * delta;

            // mesh2の頂点・制御点を平行移動する
            foreach (var v in patch2.mesh.vertices)
            {
                v.position = new PointF(v.position.X + dx, v.position.Y + dy);
            }
            foreach (var c in patch2.mesh.CopyControlPoints())
            {
                patch2.mesh.TranslateControlPoint(c.position, new PointF(c.position.X + dx, c.position.Y + dy), false);
            }
        }
示例#28
0
        //
        // Expand()
        //

        /// <summary>
        /// smesh1, smesh2の輪郭をずらして重ねる。輪郭に制御点をおいてARAPする
        /// curveOffset, curveLengthは切り口付近の補間に使う部分曲線
        /// </summary>
        static void Expand(
            PatchSkeletalMesh patch1, PatchSkeletalMesh patch2, PatchSkeleton refSkeleton,
            PatchSection section1, PatchSection section2, PatchSkeletonBone bone,
            float curveLength, float curveBuffer)
        {
            // メッシュを固定
            patch1.mesh.FreezeMesh(true);
            patch2.mesh.FreezeMesh(true);

            List <PatchVertex> rawPath1 = GetPath(patch1);
            List <PatchVertex> rawPath2 = GetPath(patch2);
            List <PointF>      path1    = rawPath1.Select(v => v.position).ToList();
            List <PointF>      path2    = rawPath2.Select(v => v.position).ToList();

            // 切り口に隣接する2曲線をそれぞれ取得
            var rawCurves1 = section2adjCurves(rawPath1, section1);
            var rawCurves2 = section2adjCurves(rawPath2, section2);

            if (rawCurves1 == null || rawCurves2 == null)
            {
                return;
            }

            var trimCurves1 = TrimCurves(rawPath1, rawCurves1, 0, curveLength);
            var trimCurves2 = TrimCurves(rawPath2, rawCurves2, 0, curveLength);

            PatchSkeletonBone refBone = RefBone(refSkeleton, bone);
            var sorted1 = GetSortedCurves(path1, trimCurves1, refBone);
            var sorted2 = GetSortedCurves(path2, trimCurves2, refBone);

            if (sorted1.Count != 2 || sorted2.Count != 2)
            {
                return;
            }

            // patch1の制御点
            patch1.mesh.ClearControlPoints();
            for (int i = 0; i < 2; i++)
            {
                foreach (var p in sorted1[i])
                {
                    patch1.mesh.AddControlPoint(p, p);
                }
            }
            patch1.mesh.BeginDeformation();

            // patch2の制御点
            patch2.mesh.ClearControlPoints();
            for (int i = 0; i < 2; i++)
            {
                foreach (var p in sorted2[i])
                {
                    patch2.mesh.AddControlPoint(p, p);
                }
            }
            patch2.mesh.BeginDeformation();

            // 第一要素、第二要素がそれぞれボーンにとって同じ側の切り口となるように並び替える
            // 切り口に近づく向きに点が並んでいる
            float h10     = CurveHeight(sorted1[0], refBone);
            float h11     = CurveHeight(sorted1[1], refBone);
            float h20     = CurveHeight(sorted2[0], refBone);
            float h21     = CurveHeight(sorted2[1], refBone);
            var   curve10 = sorted1[0].ToList();
            var   curve11 = sorted1[1].ToList();
            var   curve20 = sorted2[0].ToList();
            var   curve21 = sorted2[1].ToList();

            // curveの重心を揃える
            PointF x, y;

            BoneCoordinate(refBone, out x, out y);

            float c0   = (h10 + h20) * 0.5f;
            float dy10 = c0 - h10;

            for (int i = 0; i < curve10.Count; i++)
            {
                curve10[i] = new PointF(curve10[i].X + dy10 * y.X, curve10[i].Y + dy10 * y.Y);
            }
            float dy11 = c0 - h20;

            for (int i = 0; i < curve20.Count; i++)
            {
                curve20[i] = new PointF(curve20[i].X + dy11 * y.X, curve20[i].Y + dy11 * y.Y);
            }

            float c1   = (h11 + h21) * 0.5f;
            float dy20 = c1 - h11;

            for (int i = 0; i < curve11.Count; i++)
            {
                curve11[i] = new PointF(curve11[i].X + dy20 * y.X, curve11[i].Y + dy20 * y.Y);
            }
            float dy21 = c1 - h21;

            for (int i = 0; i < curve21.Count; i++)
            {
                curve21[i] = new PointF(curve21[i].X + dy21 * y.X, curve21[i].Y + dy21 * y.Y);
            }

            // curveをエルミート保管して繋げる
            var ends0 = new[] { curve10[0], curve10.Last(), curve20[0], curve20.Last() };
            int min0, max0;

            FMath.GetMinElement(ends0, p => FMath.ParameterOnLine(p, refBone.src.position, refBone.dst.position), out min0);
            FMath.GetMinElement(ends0, p => - FMath.ParameterOnLine(p, refBone.src.position, refBone.dst.position), out max0);

            var ends1 = new[] { curve11[0], curve11.Last(), curve21[0], curve21.Last() };
            int min1, max1;

            FMath.GetMinElement(ends1, p => FMath.ParameterOnLine(p, refBone.src.position, refBone.dst.position), out min1);
            FMath.GetMinElement(ends1, p => - FMath.ParameterOnLine(p, refBone.src.position, refBone.dst.position), out max1);

            PointF[] es = new[] {
                ends0[min0],
                ends1[min1],
                ends0[max0],
                ends1[max1],
            };
            PointF[] vs = new[] {
                new PointF(curve10[0].X - curve10[curve10.Count - 1].X, curve10[0].Y - curve10[curve10.Count - 1].Y),
                new PointF(curve11[0].X - curve11[curve11.Count - 1].X, curve11[0].Y - curve11[curve11.Count - 1].Y),
                new PointF(-(curve20[0].X - curve20[curve20.Count - 1].X), -(curve20[0].Y - curve20[curve20.Count - 1].Y)),
                new PointF(-(curve21[0].X - curve21[curve21.Count - 1].X), -(curve21[0].Y - curve21[curve21.Count - 1].Y)),
            };
            float[] ps = new[] {
                FMath.ParameterOnLine(es[0], refBone.src.position, refBone.dst.position),
                FMath.ParameterOnLine(es[1], refBone.src.position, refBone.dst.position),
                FMath.ParameterOnLine(es[2], refBone.src.position, refBone.dst.position),
                FMath.ParameterOnLine(es[3], refBone.src.position, refBone.dst.position),
            };

            for (int i = 0; i < 2; i++)
            {
                var   e1     = es[i];
                var   v1     = vs[i];
                float param1 = ps[i];

                var   e2     = es[i + 2];
                var   v2     = vs[i + 2];
                float param2 = ps[i + 2];

                if (Math.Abs(param2 - param1) <= 1e-4)
                {
                    continue;
                }
                float paramRatio = 1 / (param2 - param1);

                for (int j = 0; j < sorted1[i].Count; j++)
                {
                    float  param = FMath.ParameterOnLine(sorted1[i][j], refBone.src.position, refBone.dst.position);
                    float  t     = (param - param1) * paramRatio;
                    PointF to    = FMath.HelmitteInterporate(e1, v1, e2, v2, t);
                    patch1.mesh.TranslateControlPoint(sorted1[i][j], to, false);
                }
                for (int j = 0; j < sorted2[i].Count; j++)
                {
                    float  param = FMath.ParameterOnLine(sorted2[i][j], refBone.src.position, refBone.dst.position);
                    float  t     = (param - param1) * paramRatio;
                    PointF to    = FMath.HelmitteInterporate(e1, v1, e2, v2, t);
                    patch2.mesh.TranslateControlPoint(sorted2[i][j], to, false);
                }
            }

            // 変形
            patch1.mesh.FlushDefomation();
            patch2.mesh.FlushDefomation();

            // 変形終了
            patch1.mesh.EndDeformation();
            patch2.mesh.EndDeformation();
        }
 public void SetMeasurableCharacterRanges(CharacterRange[] ranges)
 {
     int status = SafeNativeMethods.Gdip.GdipSetStringFormatMeasurableCharacterRanges(new HandleRef(this, this.nativeFormat), ranges.Length, ranges);
     if (status != 0)
     {
         throw SafeNativeMethods.Gdip.StatusException(status);
     }
 }
示例#30
0
        /// <summary>
        /// Calculate widthLimit/height of a text (
        /// </summary>
        public static SizeF TextSize(Graphics g, string aText, Font aFont)
        {
            if (aText.Trim() == "") return new SizeF(0, 0);
            if (aText[aText.Length - 1] == ' ') { aText = aText.Substring(0, aText.Length - 1) + "/"; }
            #if CF
            return TextSize2(g, aText, aFont);
            #else
            try
            {
                if (aFont.Style == FontStyle.Bold)
                { return TextSize2(g, aText, aFont); } //MeasureCharacterRanges return wrong value if bold.

                StringFormat aFormat = StringFormat.GenericTypographic;
                //aFormat.Trimming = System.Drawing.StringTrimming.Character;
                //aFormat.FormatFlags += 16384;
                //aFormat.FormatFlags = aFormat.FormatFlags & StringFormatFlags.NoClip;

                CharacterRange[] cr = new CharacterRange[1];
                cr[0] = new CharacterRange(0, aText.Length);

                aFormat.SetMeasurableCharacterRanges(cr);

                RectangleF aRect = Screen.PrimaryScreen.Bounds;
                aRect = g.MeasureCharacterRanges(aText, aFont, aRect, aFormat)[0].GetBounds(g);
                return new SizeF(aRect.Right - aRect.Left, aRect.Height);
            }
            catch
            {
                return TextSize2(g, aText, aFont);
            }

            #endif
        }
 private void PaintException(PaintEventArgs e, Exception ex)
 {
     StringFormat stringFormat = new StringFormat {
         Alignment = StringAlignment.Near,
         LineAlignment = StringAlignment.Near
     };
     string text = ex.ToString();
     CharacterRange[] ranges = new CharacterRange[] { new CharacterRange(0, text.Length) };
     stringFormat.SetMeasurableCharacterRanges(ranges);
     int num = 2;
     Size iconSize = SystemInformation.IconSize;
     int x = num * 2;
     int y = num * 2;
     Rectangle clientRectangle = this.Control.ClientRectangle;
     Rectangle rect = clientRectangle;
     rect.X++;
     rect.Y++;
     rect.Width -= 2;
     rect.Height -= 2;
     Rectangle rectangle3 = new Rectangle(x, y, iconSize.Width, iconSize.Height);
     Rectangle layoutRect = clientRectangle;
     layoutRect.X = (rectangle3.X + rectangle3.Width) + (2 * x);
     layoutRect.Y = rectangle3.Y;
     layoutRect.Width -= (layoutRect.X + x) + num;
     layoutRect.Height -= (layoutRect.Y + y) + num;
     using (Font font = new Font(this.Control.Font.FontFamily, (float) Math.Max((SystemInformation.ToolWindowCaptionHeight - SystemInformation.BorderSize.Height) - 2, this.Control.Font.Height), GraphicsUnit.Pixel))
     {
         using (Region region = e.Graphics.MeasureCharacterRanges(text, font, layoutRect, stringFormat)[0])
         {
             Region clip = e.Graphics.Clip;
             e.Graphics.ExcludeClip(region);
             e.Graphics.ExcludeClip(rectangle3);
             try
             {
                 e.Graphics.FillRectangle(Brushes.White, clientRectangle);
             }
             finally
             {
                 e.Graphics.Clip = clip;
             }
             using (Pen pen = new Pen(Color.Red, (float) num))
             {
                 e.Graphics.DrawRectangle(pen, rect);
             }
             Icon error = SystemIcons.Error;
             e.Graphics.FillRectangle(Brushes.White, rectangle3);
             e.Graphics.DrawIcon(error, rectangle3.X, rectangle3.Y);
             layoutRect.X++;
             e.Graphics.IntersectClip(region);
             try
             {
                 e.Graphics.FillRectangle(Brushes.White, layoutRect);
                 e.Graphics.DrawString(text, font, new SolidBrush(this.Control.ForeColor), layoutRect, stringFormat);
             }
             finally
             {
                 e.Graphics.Clip = clip;
             }
         }
     }
     stringFormat.Dispose();
 }
示例#32
0
        private StylizedRowElement[] combine(DocumentRow row, ICollection<FaceApplied> styles)
        {
            if (styles == null || styles.Count == 0)
            {
                var result = new StylizedRowElement[1];
                result[0] = new StylizedRowElement(new CharacterRange(0, row.Length), style);
                return result;
            }

            var elements = new List<CharacterRange>
            {
                new CharacterRange(0, row.Length)
            };

            foreach (var styleApplied in styles)
            {
                var faceRange = styleApplied.Range;

                for (var i = 0; i < elements.Count; ++i)
                {
                    CharacterRange element = elements[i];

                    //if we are before range needed
                    if (element == faceRange)
                    {
                        continue;
                    }

                    if (element.First + element.Length < faceRange.First)
                    {
                        continue;
                    }

                    // if we are after range needed
                    if (element.First >= faceRange.First + faceRange.Length)
                    {
                        break;
                    }

                    // if face range after element start
                    if (element.First < faceRange.First)
                    {
                        var preFace = new CharacterRange(element.First, faceRange.First - element.First);

                        element.Length -= preFace.Length;
                        element.First += preFace.Length;
                        elements[i] = element;

                        elements.Insert(i++, preFace);
                    }

                    if (element.First + element.Length <= faceRange.First + faceRange.Length)
                    {
                        continue;
                    }

                    var afterOffset = faceRange.First + faceRange.Length;
                    var afterOffsetLength = element.First + element.Length - afterOffset;

                    element.Length -= afterOffsetLength;
                    elements[i] = element;

                    elements.Insert(++i, new CharacterRange(afterOffset, afterOffsetLength));
                }
            }

            var els = new List<StylizedRowElement>();
            foreach (var range in elements)
            {
                var rangeStyle = Style;
                foreach (var face in styles)
                {
                    if (!intersect(face.Range, range))
                        continue;
                    rangeStyle = rangeStyle.Combine(FindFace(face.Face).FaceStyle);
                }

                els.Add(new StylizedRowElement(range, rangeStyle));
            }

            return els.ToArray();
        }
示例#33
0
        /// <devdoc>
        ///     Calculate character ranges taking into account the locale.  Provided for surrogate chars support.
        /// </devdoc>
        private CharacterRange[] AdjustCharacterRangesForSurrogateChars(){
            string text = Text;

            if (String.IsNullOrEmpty(text)) {
                return new CharacterRange[]{};
            }

            StringInfo stringInfo = new StringInfo(text);                 
            int textLen = stringInfo.LengthInTextElements;
            ArrayList ranges = new ArrayList(Links.Count);

            foreach (Link link in Links) {
                int charStart = ConvertToCharIndex(link.Start, text);
                int charEnd = ConvertToCharIndex(link.Start + link.Length, text);
                if (LinkInText(charStart, charEnd - charStart)) {
                    int length = (int) Math.Min(link.Length, textLen - link.Start);
                    ranges.Add(new CharacterRange(charStart, ConvertToCharIndex(link.Start + length, text) - charStart));
                }
            }

            CharacterRange[] regions = new CharacterRange[ranges.Count + 1];
            ranges.CopyTo(regions, 0);
            regions[regions.Length - 1] = new CharacterRange(0, text.Length);

            return regions;
        }
示例#34
0
        private static float OverlapWidth(PatchSkeletalMesh patch1, PatchSkeletalMesh patch2, PatchSkeleton refSkeleton, PatchSection section1, PatchSection section2, PatchSkeletonBone bone, int maxLength, int maxAngle)
        {
            var refBone = RefBone(refSkeleton, bone);

            var path1   = GetPath(patch1);
            var curves1 = section2adjCurves(path1, section1);
            var sorted1 = GetSortedCurves(path1.Select(v => v.position).ToList(), curves1, refBone);

            var path2   = GetPath(patch2);
            var curves2 = section2adjCurves(path2, section2);
            var sorted2 = GetSortedCurves(path2.Select(v => v.position).ToList(), curves2, refBone);

            float[] param        = new float[] { 0, 0, 0, 0 };
            var     sortedCurves = new[] {
                sorted1[0],
                sorted1[1],
                sorted2[0],
                sorted2[1],
            };

            float minCos = (float)Math.Cos(Math.PI / 180 * maxAngle);

            for (int i = 0; i < sortedCurves.Length; i++)
            {
                var           c     = sortedCurves[i];
                var           path  = i < 2 ? path1 : path2;
                List <PointF> pts   = new List <PointF>();
                float         total = 0;
                for (int j = c.Count - 1; j >= 0; j--)
                {
                    var p = c[j];
                    pts.Add(p);
                    if (pts.Count >= 3 && FMath.GetAngleCos(pts) < minCos)
                    {
                        pts.RemoveAt(pts.Count - 1);
                        break;
                    }
                    if (pts.Count >= 2)
                    {
                        total += FMath.Distance(pts[pts.Count - 2], pts[pts.Count - 1]);
                    }
                    if (total >= maxLength)
                    {
                        pts.RemoveAt(pts.Count - 1);
                        break;
                    }
                }
                param[i] = FMath.ParameterOnLine(pts.Last(), refBone.src.position, refBone.dst.position);
            }

            float min1 = Enumerable.Range(section1.First, section1.Length).Min(idx =>
                                                                               FMath.ParameterOnLine(path1[FMath.Rem(idx, path1.Count)].position, refBone.src.position, refBone.dst.position));
            float max1 = Enumerable.Range(section1.First, section1.Length).Max(idx =>
                                                                               FMath.ParameterOnLine(path1[FMath.Rem(idx, path1.Count)].position, refBone.src.position, refBone.dst.position));

            int idx1 = Enumerable.Range(section1.First, section1.Length).First(idx =>
                                                                               max1 == FMath.ParameterOnLine(path1[FMath.Rem(idx, path1.Count)].position, refBone.src.position, refBone.dst.position));

            float min2 = Enumerable.Range(section2.First, section2.Length).Min(idx =>
                                                                               FMath.ParameterOnLine(path2[FMath.Rem(idx, path2.Count)].position, refBone.src.position, refBone.dst.position));
            float max2 = Enumerable.Range(section2.First, section2.Length).Max(idx =>
                                                                               FMath.ParameterOnLine(path2[FMath.Rem(idx, path2.Count)].position, refBone.src.position, refBone.dst.position));

            float idx2 = Enumerable.Range(section2.First, section2.Length).First(idx =>
                                                                                 max2 == FMath.ParameterOnLine(path2[FMath.Rem(idx, path2.Count)].position, refBone.src.position, refBone.dst.position));

            System.Diagnostics.Debug.Assert(param[0] <= max1);
            System.Diagnostics.Debug.Assert(param[1] <= max1);
            System.Diagnostics.Debug.Assert(param[2] >= min2);
            System.Diagnostics.Debug.Assert(param[3] >= min2);

            float[] dParams = new[] {
                Math.Max(0, min1 - param[0]),
                Math.Max(0, min1 - param[1]),
                Math.Max(0, param[2] - max2),
                Math.Max(0, param[3] - max2),
            };

            float minDParam    = dParams.Min();
            float boarderWidth = minDParam * FMath.Distance(refBone.src.position, refBone.dst.position);

            return(boarderWidth);
        }
示例#35
0
 public StylizedRowElement(CharacterRange range, Style style)
 {
     this.range = range;
     this.style = style;
 }
示例#36
0
        //-----------------------------------------------------------------------------------
        // Deform()
        //-----------------------------------------------------------------------------------

        /// <summary>
        /// 切り口付近で2つのsmeshが重なるように変形する
        /// patch2がdst方向
        /// </summary>
        private static void Deform(PatchSkeletalMesh patch1, PatchSkeletalMesh patch2, PatchSkeleton refSkeleton, PatchSection section1, PatchSection section2, PatchSkeletonBone crossingBone)
        {
            if (patch1 == null || patch2 == null)
            {
                return;
            }

            // 各メッシュを大雑把にスケルトンに合わせる
            PatchSkeletonFitting.Fitting(patch1, refSkeleton);
            PatchSkeletonFitting.Fitting(patch2, refSkeleton);

            // TODO: サイズの修正

            // 回転はFitting()でやってるから必要ない

            // 位置の調整

            float overlap = OverlapWidth(patch1, patch2, refSkeleton, section1, section2, crossingBone, 100, 45);

            AdjustHeight(patch1, patch2, refSkeleton, section1, section2, crossingBone);
            OverlayPatches(patch1, patch2, refSkeleton, section1, section2, crossingBone, overlap);

#if _DEBUG
            PatchSkeletalMeshRenderer.ToBitmap(patch1).Save("output_Connector2/4_patch1.png");
            PatchSkeletalMeshRenderer.ToBitmap(patch2).Save("output_Connector2/4_patch2.png");
#endif
            // メッシュを伸ばして繋げる
            Expand(patch1, patch2, refSkeleton, section1, section2, crossingBone, overlap, overlap);
        }
示例#37
0
 private static bool intersect(CharacterRange lhs, CharacterRange rhs)
 {
     var min = Math.Max(lhs.First, rhs.First);
     var max = Math.Min(lhs.First + lhs.Length, rhs.First + rhs.Length);
     return min < max;
 }
示例#38
0
        /// <summary>
        /// Measures the location of an arbritrary # of words within a string
        /// </summary>
        private WordStartFinish[] MeasureString(string s, Graphics g, Font drawFont, StringFormat drawFormat, 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;
            CharacterRange[] cra32 = new 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 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;
        }
示例#39
0
 static PatchSkeletalMesh Combine(PatchSkeletalMesh smesh1, PatchSkeletalMesh smesh2, PatchSection section1, PatchSection section2)
 {
     throw new NotImplementedException();
 }
        private void RenderRowView(
            Graphics g,
            DocumentRowView view,
            float offset,
            CharacterRange selectionRange)
        {
            for (int i = 0; i < view.parts.Length; ++i)
            {
                StylizedRowElement atom = view.parts[i];
                string atomRaw = view.partRaws[i];

                CharacterRangeTrio trio = intersectAtomWithSelection(atom.range, selectionRange);
                if (trio.first.Length > 0)
                {
                    trio.first.First -= atom.range.First;

                    offset += DrawStringPart(trio.first, g, atomRaw, atom.style, offset).Width;
                }

                if (trio.second.Length > 0)
                {
                    trio.second.First -= atom.range.First;

                    Style thisStyle = atom.style.combine(selectionStyle);

                    offset += DrawStringPart(trio.second, g, atomRaw, thisStyle, offset).Width;
                }

                if (trio.third.Length > 0)
                {
                    trio.third.First -= atom.range.First;

                    offset += DrawStringPart(trio.third, g, atomRaw, atom.style, offset).Width;
                }
            }
            renderStuff.LineFrame = offset;
        }
示例#41
0
		[Test] // adapted from bug #78777
		public void MeasureCharacterRanges_TwoLines ()
		{
			if (font == null)
				Assert.Ignore ("Couldn't create required font");

			string text = "this\nis a test";
			CharacterRange[] ranges = new CharacterRange[2];
			ranges[0] = new CharacterRange (0, 5);
			ranges[1] = new CharacterRange (5, 9);

			StringFormat string_format = new StringFormat ();
			string_format.FormatFlags = StringFormatFlags.NoClip;
			string_format.SetMeasurableCharacterRanges (ranges);

			using (Bitmap bitmap = new Bitmap (20, 20)) {
				using (Graphics g = Graphics.FromImage (bitmap)) {
					SizeF size = g.MeasureString (text, font, new Point (0, 0), string_format);
					RectangleF layout_rect = new RectangleF (0.0f, 0.0f, size.Width, size.Height);
					Region[] regions = g.MeasureCharacterRanges (text, font, layout_rect, string_format);

					Assert.AreEqual (2, regions.Length, "Length");
					Assert.AreEqual (regions[0].GetBounds (g).Height, regions[1].GetBounds (g).Height, "Height");
				}
			}
		}
        private void RenderRowViewWithCursor(
            Graphics g,
            DocumentRowView view,
            float offset,
            int cursor,
            CharacterRange selectionRange)
        {
            for (int i = 0, last = view.parts.Length - 1; i <= last; ++i)
            {
                StylizedRowElement atom = view.parts[i];
                string atomRaw = view.partRaws[i];

                if (i == last && cursor >= atom.range.Length)
                {
                    cursor = atom.range.Length - 1;
                }

                CharacterRangeTrio trio = intersectAtomWithSelection(atom.range, selectionRange);

                if (trio.first.Length > 0) {
                    trio.first.First -= atom.range.First;

                    Style thisStyle = atom.style;

                    float offsetChange = DrawStringPart(trio.first, g, atomRaw, thisStyle, offset).Width;

                    cursor -= drawCursor(cursor, trio.first, offset, g, atomRaw, thisStyle);

                    offset += offsetChange;
                }

                if (trio.second.Length > 0)
                {
                    trio.second.First -= atom.range.First;

                    Style thisStyle = atom.style.combine(selectionStyle);

                    float offsetChange = DrawStringPart(trio.second, g, atomRaw, thisStyle, offset).Width;

                    cursor -= drawCursor(cursor, trio.second, offset, g, atomRaw, thisStyle);

                    offset += offsetChange;
                }

                if (trio.third.Length > 0)
                {
                    trio.third.First -= atom.range.First;

                    Style thisStyle = atom.style;

                    float offsetChange = DrawStringPart(trio.third, g, atomRaw, atom.style, offset).Width;

                    cursor -= drawCursor(cursor, trio.third, offset, g, atomRaw, thisStyle);

                    offset += offsetChange;
                }
            }
            renderStuff.LineFrame = offset;
        }
示例#43
0
		public void MeasureCharacterRanges_Prefix ()
		{
			if (font == null)
				Assert.Ignore ("Couldn't create required font");

			string text = "Hello &Mono::";
			CharacterRange[] ranges = new CharacterRange[1];
			ranges[0] = new CharacterRange (5, 4);

			StringFormat string_format = new StringFormat ();
			string_format.SetMeasurableCharacterRanges (ranges);

			using (Bitmap bitmap = new Bitmap (20, 20)) {
				using (Graphics g = Graphics.FromImage (bitmap)) {
					SizeF size = g.MeasureString (text, font, new Point (0, 0), string_format);
					RectangleF layout_rect = new RectangleF (0.0f, 0.0f, size.Width, size.Height);

					// here & is part of the measure and visible
					string_format.HotkeyPrefix = HotkeyPrefix.None;
					Region[] regions = g.MeasureCharacterRanges (text, font, layout_rect, string_format);
					RectangleF bounds_none = regions[0].GetBounds (g);

					// here & is part of the measure (range) but visible as an underline
					string_format.HotkeyPrefix = HotkeyPrefix.Show;
					regions = g.MeasureCharacterRanges (text, font, layout_rect, string_format);
					RectangleF bounds_show = regions[0].GetBounds (g);
					Assert.IsTrue (bounds_show.Width < bounds_none.Width, "Show<None");

					// here & is part of the measure (range) but invisible
					string_format.HotkeyPrefix = HotkeyPrefix.Hide;
					regions = g.MeasureCharacterRanges (text, font, layout_rect, string_format);
					RectangleF bounds_hide = regions[0].GetBounds (g);
					Assert.AreEqual (bounds_hide.Width, bounds_show.Width, "Hide==None");
				}
			}
		}
        private static CharacterRange intersect(CharacterRange range1, CharacterRange range2)
        {
            int start = Math.Max(range1.First, range2.First);
            int end = Math.Min(range1.First + range1.Length, range2.First + range2.Length);

            if (end > start)
                return new CharacterRange(start, end - start);
            return new CharacterRange();
        }
示例#45
0
        private string[] MeasureString(PageText pt, Graphics g, out float[] width)
        {
            StyleInfo si = pt.SI;
            string s = pt.Text;

            Font drawFont=null;
            StringFormat drawFormat=null;
            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 Font(StyleInfo.GetFontFamily(si.FontFamilyFull), si.FontSize, fs);
                drawFormat = new StringFormat();
                drawFormat.Alignment = 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);
                    CharacterRange[] cra = new 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;
                        CharacterRange cr = new 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;
                    CharacterRange crs = cra[startLoc];
                    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();
            }
        }
示例#46
0
        // 切り口に隣接する部分パス(2つ)を返す
        // この部分を引き伸ばしてメッシュを繋げる
        static Tuple <CharacterRange, CharacterRange> section2adjCurves(List <PatchVertex> path, PatchSection section)
        {
            if (section.Length <= 0 || path == null || path.Count < 5)
            {
                return(null);
            }
            int start1 = FMath.Rem(section.First, path.Count);
            int end1   = start1 - 2;
            int start2 = FMath.Rem(section.First + section.Length - 1, path.Count);
            int end2   = start2 + 2;

            int part = path[start1].part;

            System.Diagnostics.Debug.Assert(part == path[start2].part);

            for (int i = 0; i < path.Count / 2; i++)
            {
                int idx1 = FMath.Rem(start1 - i, path.Count);
                int idx2 = FMath.Rem(start2 + i, path.Count);
                if (path[idx1].part != part || path[idx2].part != part)
                {
                    break;
                }
                end1 = idx1;
                end2 = idx2;
                if (FMath.Rem(end2 - end1, path.Count) <= 2)
                {
                    break;
                }
            }

            var r1 = rangeOnLoop(end1, start1, path.Count);
            var r2 = rangeOnLoop(start2, end2, path.Count);

            if (r1.Length <= 0 || r2.Length <= 0)
            {
                return(null);
            }

            return(new Tuple <CharacterRange, CharacterRange>(r1, r2));
        }
示例#47
0
        /// <summary>
        /// Measures the location of words within a string;  limited by .Net 1.1 to 32 words
        ///     MEASUREMAX is a constant that defines that limit
        /// </summary>
        /// <param name="s"></param>
        /// <param name="g"></param>
        /// <param name="drawFont"></param>
        /// <param name="drawFormat"></param>
        /// <param name="cra"></param>
        /// <returns></returns>
        private WordStartFinish[] MeasureString32(string s, Graphics g, Font drawFont, StringFormat drawFormat, CharacterRange[] cra)
        {
            if (s == null || s.Length == 0)
                return null;

            drawFormat.SetMeasurableCharacterRanges(cra);
            Region[] rs = new Region[cra.Length];
            rs = g.MeasureCharacterRanges(s, drawFont, new RectangleF(0, 0, float.MaxValue, float.MaxValue),
                drawFormat);
            WordStartFinish[] sz = new WordStartFinish[cra.Length];
            int isz = 0;
            foreach (Region r in rs)
            {
                RectangleF mr = r.GetBounds(g);
                sz[isz].start = RSize.PointsFromPixels(g, mr.Left);
                sz[isz].end = RSize.PointsFromPixels(g, mr.Right);
                isz++;
            }
            return sz;
        }
        private RectangleF[] MeasureStringParts(CharacterRange[] range, Graphics g, string str, Style style)
        {
            UpdateTabStop(str, style);

            stringFormat.SetMeasurableCharacterRanges(range);

            Region[] regn = g.MeasureCharacterRanges(str, FontCache.get(style),
                                                     RectangleF.Empty, stringFormat);

            return Array.ConvertAll<Region, RectangleF>(regn, delegate(Region rgn)
            {
                return rgn.GetBounds(g);
            });
        }