public void GetHashCode_WhenConstructedWithTheSameCharacters_ReturnsTheSameValue(char min, char max) { var subjectA = new CharacterRange(min, max); var subjectB = new CharacterRange(min, max); Assert.That(subjectA.GetHashCode(), Is.EqualTo(subjectB.GetHashCode())); }
public void Equals_WithNullReference_ReturnsFalse() { var subjectA = new CharacterRange(char.MinValue, char.MaxValue); var subjectB = (object)null; Assert.That(subjectA.Equals(subjectB), Is.False); }
public void Equals_WhenConstructedWithTheSameCharacters_ReturnsTrue(char min, char max) { var subjectA = new CharacterRange(min, max); var subjectB = new CharacterRange(min, max); Assert.That(subjectA.Equals(subjectB), Is.True); }
public void Equals_WithOtherObject_ReturnsFalse() { var subjectA = new CharacterRange(char.MinValue, char.MaxValue); var subjectB = new object(); Assert.That(subjectA.Equals(subjectB), Is.False); }
public void Equals_WithDifferentMinCharacter_ReturnsFalse(char minA, char minB, char max) { Assume.That(minA, Is.Not.EqualTo(minB)); var subjectA = new CharacterRange(minA, max); var subjectB = new CharacterRange(minB, max); Assert.That(subjectA.Equals(subjectB), Is.False); }
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 int ec = sb.Length; if (i != parts.Length - 1) // last item doesn't need blank { sb.Append(" "); } 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(); float[] 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]; // length of the first string ts; for (int i = 1; i < cra.Length; i++) { cwidth = wordLocations[i] - (startLoc == 0 ? 0 : wordLocations[startLoc - 1]); if (cwidth > ptWidth) { // time for a new line cre = cra[i - 1]; ts = wfl.Substring(crs.First, cre.First + cre.Length - crs.First); startLoc = i; crs = cre = cra[startLoc]; lines.Add(ts); lineWidths.Add(cwidth); } else { cre = cra[i]; } } ts = fl.Substring(crs.First, cre.First + cre.Length - crs.First); lines.Add(ts); lineWidths.Add(cwidth); } // create the final array from the Lists string[] la = lines.ToArray(); width = lineWidths.ToArray(); return(la); } finally { if (drawFont != null) { drawFont.Dispose(); } if (drawFormat != null) { drawFont.Dispose(); } } }
private void lbResults_DrawItem(object sender, DrawItemEventArgs e) { e.DrawBackground(); bool selected = (e.State & DrawItemState.Selected) == DrawItemState.Selected; if ((e.Index < 0) || (e.Index >= SearchResults.Count)) { return; } var search = ActiveSearchQuery; if (search == null) { return; } using (var backgroundBrush = new SolidBrush(selected ? SystemColors.Highlight : lbResults.BackColor)) using (var brush = new SolidBrush(selected ? SystemColors.HighlightText : lbResults.ForeColor)) { var item = SearchResults[e.Index]; var format = StringFormat.GenericTypographic; format.LineAlignment = StringAlignment.Near; format.FormatFlags = StringFormatFlags.NoWrap; format.Trimming = StringTrimming.EllipsisPath; format.Alignment = StringAlignment.Near; var rect = new RectangleF(e.Bounds.X, e.Bounds.Y + 1, e.Bounds.Width - LineNumberWidth, LineHeight); e.Graphics.DrawString(item.Filename, lbResults.Font, brush, rect, format); format.Trimming = StringTrimming.Character; format.Alignment = StringAlignment.Far; rect = new RectangleF(e.Bounds.X, e.Bounds.Y + 1, e.Bounds.Width, LineHeight); e.Graphics.DrawString(item.LineNumber.ToString(), lbResults.Font, brush, rect, format); string context = item.Context; MatchEvaluator blankEvaluator = (m) => new String(' ', m.Length); string cleanContext = search.Regex.Replace(item.Context, blankEvaluator); format.Trimming = StringTrimming.None; format.Alignment = StringAlignment.Near; rect = new RectangleF(e.Bounds.X + 6, e.Bounds.Y + LineHeight + 1, e.Bounds.Width - 6, e.Bounds.Height - LineHeight); using (var pen = new Pen(SystemColors.ButtonShadow, 1.0f)) e.Graphics.DrawLine(pen, rect.Location, new PointF(rect.Right, rect.Top)); e.Graphics.DrawString(cleanContext, lbResults.Font, brush, rect, format); using (var maskBrush = new SolidBrush(Color.FromArgb(127, selected ? SystemColors.Highlight : lbResults.BackColor))) { var mrect = new RectangleF(e.Bounds.X + 6, e.Bounds.Y + LineHeight + 1, e.Bounds.Width - 6, LineHeight); e.Graphics.FillRectangle(maskBrush, mrect); mrect = new RectangleF(e.Bounds.X + 6, e.Bounds.Y + (LineHeight * 3) + 1, e.Bounds.Width - 6, LineHeight); e.Graphics.FillRectangle(maskBrush, mrect); } var matches = search.Regex.Matches(context); if (matches.Count > 0) { var ranges = (from m in matches.Cast <Match>() select new CharacterRange(m.Index, m.Length)).ToArray(); int blockSize = Math.Min(32, ranges.Length); var temp = new CharacterRange[blockSize]; e.Graphics.ResetClip(); e.Graphics.ExcludeClip(e.Graphics.Clip); for (int i = 0; i < ranges.Length; i += 32) { Array.Copy(ranges, i, temp, 0, Math.Min(blockSize, ranges.Length - i)); format.SetMeasurableCharacterRanges(temp); foreach (var region in e.Graphics.MeasureCharacterRanges(item.Context, lbResults.Font, rect, format)) { e.Graphics.SetClip(region, System.Drawing.Drawing2D.CombineMode.Union); } } using (var highlightBrush = new SolidBrush(SystemColors.Highlight)) using (var highlightTextBrush = new SolidBrush(SystemColors.HighlightText)) { e.Graphics.FillRectangle(highlightBrush, rect); e.Graphics.DrawString(context, lbResults.Font, highlightTextBrush, rect, format); } e.Graphics.ResetClip(); } } e.DrawFocusRectangle(); }
private void CalcOrMake(bool makeTexture) { gridSize = 1; while ((gridSize * gridSize) < GlyphItems.Count) { gridSize *= 2; } int cellSize = 2; while (cellSize < cellHeight) { cellSize *= 2; } cellHeight = cellSize; int textureSize = cellHeight * gridSize; TextObject.Text = ""; TextObject.FontSize = (float)cellHeight * .50f; System.Drawing.Font font = TextObject.Font; StringFormat sf = new StringFormat(); sf.Alignment = StringAlignment.Near; Bitmap bmp; if (makeTexture) { bmp = new Bitmap(textureSize, textureSize); } else { bmp = new Bitmap(20, 20); } Graphics g = Graphics.FromImage(bmp); int count = 0; g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; CharacterRange[] ranges = new CharacterRange[1]; ranges[0] = new CharacterRange(0, 1); sf.SetMeasurableCharacterRanges(ranges); foreach (GlyphItem item in GlyphItems.Values) { int x = (int)(count % gridSize) * cellHeight; int y = (int)(count / gridSize) * cellHeight; string text = new string(item.Glyph, 1); item.Size = g.MeasureString(text, font); Region[] reg = g.MeasureCharacterRanges(text, font, new RectangleF(new PointF(0, 0), item.Size), sf); RectangleF rectf = reg[0].GetBounds(g); item.Extents = new SizeF(rectf.Width, rectf.Height); if (item.Extents.Width == 0) { item.Extents = item.Size; } float div = textureSize; item.UVRect = new RectangleF(x / div, y / div, item.Size.Width / div, item.Size.Height / div); item.UVRect = new RectangleF((x + rectf.X) / div, (y + rectf.Y) / div, rectf.Width / div, rectf.Height / div); if (makeTexture) { g.DrawString(text, font, Brushes.White, x, y, sf); } count++; } g.Dispose(); GC.SuppressFinalize(g); if (makeTexture) { if (texture != null) { texture.Dispose(); GC.SuppressFinalize(texture); texture = null; } texture = Texture11.FromBitmap(RenderContext11.PrepDevice, bmp); textureDirty = false; } else { textureDirty = true; } bmp.Dispose(); GC.SuppressFinalize(bmp); dirty = false; }
private void CreateLinkPieces() { if (Text.Length == 0) { SetStyle(ControlStyles.Selectable, false); TabStop = false; link_area.Start = 0; link_area.Length = 0; return; } if (Links.Count == 1 && Links[0].Start == 0 && Links[0].Length == -1) { Links[0].Length = Text.Length; } SortLinks(); // Set the LinkArea values based on first link. if (Links.Count > 0) { link_area.Start = Links[0].Start; link_area.Length = Links[0].Length; } else { link_area.Start = 0; link_area.Length = 0; } TabStop = (LinkArea.Length > 0); SetStyle(ControlStyles.Selectable, TabStop); /* don't bother doing the rest if our handle hasn't been created */ if (!IsHandleCreated) { return; } ArrayList pieces_list = new ArrayList(); int current_end = 0; for (int l = 0; l < sorted_links.Length; l++) { int new_link_start = sorted_links[l].Start; if (new_link_start > current_end) { /* create/push a piece * containing the text between * the previous/new link */ ArrayList text_pieces = CreatePiecesFromText(current_end, new_link_start - current_end, null); pieces_list.AddRange(text_pieces); } /* now create a group of pieces for * the new link (split up by \n's) */ ArrayList link_pieces = CreatePiecesFromText(new_link_start, sorted_links[l].Length, sorted_links[l]); pieces_list.AddRange(link_pieces); sorted_links[l].pieces.AddRange(link_pieces); current_end = sorted_links[l].Start + sorted_links[l].Length; } if (current_end < Text.Length) { ArrayList text_pieces = CreatePiecesFromText(current_end, Text.Length - current_end, null); pieces_list.AddRange(text_pieces); } pieces = new Piece[pieces_list.Count]; pieces_list.CopyTo(pieces, 0); CharacterRange[] ranges = new CharacterRange[pieces.Length]; for (int i = 0; i < pieces.Length; i++) { ranges[i] = new CharacterRange(pieces[i].start, pieces[i].length); } string_format.SetMeasurableCharacterRanges(ranges); Region[] regions = TextRenderer.MeasureCharacterRanges(Text, ThemeEngine.Current.GetLinkFont(this), PaddingClientRectangle, string_format); for (int i = 0; i < pieces.Length; i++) { pieces[i].region = regions[i]; pieces[i].region.Translate(Padding.Left, Padding.Top); } Invalidate(); }
public ConnectPair(BoneAnnotation bone, SegmentMeshInfo meshInfo1, CharacterRange section1, SegmentMeshInfo meshInfo2, CharacterRange section2) { this.bone = bone; this.meshInfo1 = meshInfo1; this.sectionRange1 = section1; this.meshInfo2 = meshInfo2; this.sectionRange2 = section2; }
public CharacterRangeSegment(CharacterRange range) { Range = range; }
private void CalculateLines(Graphics g) { if (!this.Modified) { return; } this.lines.Clear(); this.lines.Add(0); StringFormat stringFormat = new StringFormat(); stringFormat.FormatFlags = StringFormatFlags.MeasureTrailingSpaces; RectangleF layoutRect = new RectangleF(0.0f, (float)this.startY, (float)this.Width, (float)(this.Height - this.startY + this.lineHeight)); int First; for (First = 0; First < this.Text.Length; ++First) { if (this.Text[First] == '\r') { this.lines.Add(++First); } else { CharacterRange[] ranges = new CharacterRange[1] { new CharacterRange(First, 1) }; stringFormat.SetMeasurableCharacterRanges(ranges); RectangleF bounds = g.MeasureCharacterRanges(this.Text, this.Font, layoutRect, stringFormat)[0].GetBounds(g); if (this.input == Keys.End && (double)bounds.Height == 0.0 && this.Text[First] != ' ') { layoutRect.Height += (float)this.lineHeight; --First; } else if ((double)bounds.Y > (double)(this.lineHeight * this.lines.Count + this.startY) - (double)bounds.Height / 2.0) { this.lines.Add(First - 1); } } } if ((double)layoutRect.Height > (double)this.maxHeight) { this.maxHeight = (int)layoutRect.Height; } if (First == this.Text.Length && this.lines[this.lines.Count - 1] != this.Text.Length - 1) { this.lines.Add(this.Text.Length - 1); } Point empty = Point.Empty; WPTextBox.GetCaretPos(ref empty); this.lineIndex = (int)((double)(empty.Y - this.startY) / (double)this.lineHeight + 1.5); if (this.lineIndex < 1) { this.lineIndex = 1; this.startY = 0; } if (this.CharIndex == this.Text.Length || this.lineIndex >= this.lines.Count) { this.lineIndex = this.Text[this.Text.Length - 1] != '\n' ? this.lines.Count - 1 : this.lines.Count; } if (this.input == Keys.End) { this.startY = this.Height - this.lineHeight * this.lines.Count; if (this.startY > 0) { this.startY = 0; } } this.Modified = false; }
public static bool op_Inequality(CharacterRange cr1, CharacterRange cr2) {}
public void Undo(ChangeDescription change) { UpdateText(change.Start, change.TextAfter.Length, change.TextBefore); m_storedSelection = change.SelectionBefore; }
// Analyzes the changes made to the editor between the last call to AnalyzeChange // and this one. It is important that this method get called every time the selection in the // editor changes, so the tracker state follows the editor state accurately. public ChangeDescription AnalyzeChange() { // When changes occur, they must occur where the selection is. What we do here is to keep // track of where the selection is, and where it was. We know that if the selection started n // characters from the front of the string last time, and m characters from the front of the // selection last time, then there can have been no changes in the first min(n, m) characters. // Similarly, if the selection ended x characters from the end of the string last time, and ends // y characters from the end of the string this time, there can have been no changes in the last // min(x, y) characters. Then we simply compare between those two points to figure out what // actually changed. int _length = m_editor.TextLength; CharacterRange _selection = m_editor.SelectionRange; // In some situations, the selection can extend one character past the end of the text. We just // treat it as if it went to the end. if ((_selection.First + _selection.Length) > _length) { _selection.Length = _length - _selection.First; } CharacterRange _previousSelection = m_storedSelection; m_storedSelection = _selection; // Count of characters that are guaranteed the same at the start of the new and old strings int _sameUntil = Math.Min(_selection.First, _previousSelection.First); // Negative of the count of characters that are guaranteed the same at the end of the new and old strings int _sameAfter = -Math.Min(_length - _selection.First - _selection.Length, m_previousText.Length - _previousSelection.First - _previousSelection.Length); // If the first n characters are the same, and the last m characters are the same, // and the sum of m and n equals the length of the string if ((_sameUntil - _sameAfter) == _length) { // and the length hasn't changed, if (_length == m_previousText.Length) { // then the string is unchanged return(new ChangeDescription(_previousSelection, _selection)); } } // Grab the subset of the text that's in the "potentially changed" range string _contents = m_editor.GetTextRange(new CharacterRange(_sameUntil, _length + _sameAfter - _sameUntil)); int _frontIndex = _sameUntil; // Iterate forward through the string, looking for where it starts to differ from previous int _scanTo = _length + _sameAfter; while (_frontIndex < _scanTo) { // If the new string is longer, then obviously it differs starting where the old one ends if (_frontIndex >= m_previousText.Length) { break; } int _contentsIndex = _frontIndex - _sameUntil; // If the old string is longer, then obvious it differs starting wher the new one ends if (_contentsIndex >= _contents.Length) { break; } if (m_previousText[_frontIndex] != _contents[_contentsIndex]) { break; } ++_frontIndex; } // Back index is actually a count of characters from the end of the string. Zero indicates the // position just after the last character in the string. Maybe it should be a negative number, // but I chose to make it positive int _backIndex = _sameAfter; // Iterate backward through the string, looking for where it stops differing from previous while (true) { int _previousIndex = m_previousText.Length + _backIndex - 1; int _contentsIndex = _contents.Length + _sameAfter + _backIndex - 1; // If we've iterated to a point where we slam into frontIndex, we've already checked // this far, and there's no need to go farther if (_previousIndex <= _frontIndex) { break; } // If we've iterated to a point where we slam into frontIndex in the new string, we've // already checked this far, and there's no need to go farther if (_contentsIndex - _sameAfter <= _frontIndex) { break; } // If we've walked off the front of the new string, then the old string was longer, and // we can stop looking for differences if (_contentsIndex < 0) { break; } if (m_previousText[_previousIndex] != _contents[_contentsIndex]) { break; } --_backIndex; } // Sometimes we can wind up walking past the front index // If the new text is shorter than the old text if (_length < m_previousText.Length) { // And if the back index falls before the front index if ((_length + _backIndex) < _frontIndex) { // Set them to be the same _backIndex = _length - _frontIndex; } } // Otherwise, if the old text is shorter than the new text else if (_length > m_previousText.Length) { // And the back index falls before the front index if ((m_previousText.Length + _backIndex) < _frontIndex) { // Set them to be the same _backIndex = _frontIndex - m_previousText.Length; } } // If the front and back indices indicate the same point in the current text if ((_length + _backIndex) == _frontIndex) { // and in the previous text if (_length == m_previousText.Length) { // Then nothing has changed return(new ChangeDescription(_previousSelection, _selection)); } } int _previousChangeStart = _frontIndex; int _previousChangeEnd = m_previousText.Length + _backIndex; int _capacity = _previousChangeEnd - _previousChangeStart; string _oldText = ""; if (_capacity > 0) { StringBuilder _bld = new StringBuilder(_previousChangeEnd - _previousChangeStart); for (int i = _previousChangeStart; i < _previousChangeEnd; ++i) { _bld.Append(m_previousText[i]); } _oldText = _bld.ToString(); } // Update the string that tracks the previous contents to match the new contents int _currentChangeStart = _frontIndex; int _currentChangeEnd = _length + _backIndex; string _newText = m_editor.GetTextRange(new CharacterRange(_currentChangeStart, _currentChangeEnd - _currentChangeStart)); UpdateText(_previousChangeStart, _previousChangeEnd - _previousChangeStart, _newText); return(new ChangeDescription(_frontIndex, _previousSelection, _oldText, _selection, _newText)); }
public void Redo(ChangeDescription change) { UpdateText(change.Start, change.TextBefore.Length, change.TextAfter); m_storedSelection = change.SelectionAfter; }
public ChangeTracker(IEditor editor) { m_editor = editor; m_storedSelection = editor.SelectionRange; m_previousText = new StringBuilder(editor.Text); }
private char GetRandomChar() { CharacterRange range = _charRanges[_random.Next(_charRanges.Length)]; return((char)(range.Start + _random.Next(range.End - range.Start))); }
// Gets the bounds of each character in a line of text. // Each line is processed in blocks of 32 characters (GdiPlus.MaxMeasurableCharacterRanges). IEnumerable <RectangleF> MeasureGlyphExtents( ref TextBlock block, string text, IntPtr native_graphics, IntPtr native_font, IntPtr native_string_format, ref RectangleF layoutRect, out float max_width, out float max_height) { measured_glyphs.Clear(); max_width = layoutRect.Left; max_height = layoutRect.Top; float last_line_width = 0, last_line_height = 0; int current = 0; while (current < text.Length) { int num_characters = (text.Length - current) > GdiPlus.MaxMeasurableCharacterRanges ? GdiPlus.MaxMeasurableCharacterRanges : text.Length - current; int status = 0; // Prepare the character ranges and region structs for the measurement. for (int i = 0; i < num_characters; i++) { if (text[current + i] == '\n' || text[current + i] == '\r') { throw new NotSupportedException(); } characterRanges[i] = new CharacterRange(current + i, 1); IntPtr region; status = GdiPlus.CreateRegion(out region); regions[i] = region; Debug.Assert(status == 0, String.Format("GDI+ error: {0}", status)); } status = GdiPlus.SetStringFormatMeasurableCharacterRanges(native_string_format, num_characters, characterRanges); Debug.Assert(status == 0, String.Format("GDI+ error: {0}", status)); status = GdiPlus.MeasureCharacterRanges(native_graphics, text, text.Length, native_font, ref layoutRect, native_string_format, num_characters, regions); Debug.Assert(status == 0, String.Format("GDI+ error: {0}", status)); // Read back the results of the measurement. for (int i = 0; i < num_characters; i++) { RectangleF rect = new RectangleF(); GdiPlus.GetRegionBounds(regions[i], native_graphics, ref rect); Debug.Assert(status == 0, String.Format("GDI+ error: {0}", status)); GdiPlus.DeleteRegion(regions[i]); Debug.Assert(status == 0, String.Format("GDI+ error: {0}", status)); if (rect.Bottom > max_height) { max_height = rect.Bottom; } if (rect.Right > max_width) { max_width = rect.Right; } if (rect.X > last_line_width) { last_line_width = rect.X; } if (rect.Y > last_line_height) { last_line_height = rect.Y; } measured_glyphs.Add(rect); } current += num_characters; } // Make sure the current height is updated, if the the current line has wrapped due to word-wraping. // Otherwise, the next line will overlap with the current one. if (measured_glyphs.Count > 1) { if ((block.Direction & TextDirection.Vertical) == 0) { if (layoutRect.Y < last_line_height) { layoutRect.Y = last_line_height; } } else { if (layoutRect.X < last_line_width) { layoutRect.X = last_line_width; } } } // Mono's GDI+ implementation suffers from an issue where the specified layoutRect is not taken into // account. We will try to improve the situation by moving text to the correct location on this // error condition. This will not help word wrapping, but it is better than nothing. // TODO: Mono 2.8 is supposed to ship with a Pango-based GDI+ text renderer, which should not // suffer from this bug. Verify that this is the case and remove the hack. if (Configuration.RunningOnMono && (layoutRect.X != 0 || layoutRect.Y != 0) && measured_glyphs.Count > 0) { for (int i = 0; i < measured_glyphs.Count; i++) { RectangleF rect = measured_glyphs[i]; rect.X += layoutRect.X; rect.Y += layoutRect.Y; measured_glyphs[i] = rect; } } return(measured_glyphs); }
public CharacterRange(char lowChar, char highChar) : base(CharacterRange.GetCharArray(lowChar, highChar).ToArray()) { }
public TextToFind(CharacterRange chrRange, string searchText) { _sciTextToFind.chrg = chrRange; _sciTextToFind.lpstrText = Marshal.StringToHGlobalAnsi(searchText); }
public HeaderMapping(ConversionContext ctx, HeaderPart part, CharacterRange hdr) : base(ctx, part) { _hdr = hdr; }
public static int MeasureDisplayStringWidth(string text, Font font) { if (text.Length < 1) return 0; Bitmap image = new Bitmap(1, 1); Graphics g = Graphics.FromImage(image); StringFormat stringFormat = new StringFormat(); RectangleF layoutRect = new RectangleF(0f, 0f, 1000f, 1000f); CharacterRange[] ranges = new CharacterRange[] { new CharacterRange(0, text.Length) }; Region[] regionArray = new Region[1]; stringFormat.SetMeasurableCharacterRanges(ranges); layoutRect = g.MeasureCharacterRanges(text, font, layoutRect, stringFormat)[0].GetBounds(g); g.Dispose(); image.Dispose(); return (int)(layoutRect.Right + 1f); }
private void m_treeView_DrawNode(object sender, DrawTreeNodeEventArgs e) { NodeData data = e.Node.Tag as NodeData; if(data == null) { e.DrawDefault = true; return; } string text = data.FormattedText; var graphics = e.Graphics; Font currentFont = e.Node.NodeFont ?? e.Node.TreeView.Font; Brush currentBrush = (e.State & TreeNodeStates.Selected) != 0 ? Brushes.White : Brushes.Black; FontSet fontSet = IsFiltered(data.Name) ? m_filteredFonts : m_normalFonts; var matches = m_regex.Matches(text); if(matches.Count == 0) { e.DrawDefault = true; return; } bool parentSelected = e.Node.Parent != null && e.Node.Parent.IsSelected; int rectX = e.Bounds.X > 0 ? e.Bounds.X : 0; if(parentSelected) graphics.FillRectangle(Brushes.AliceBlue, rectX, e.Bounds.Y, m_treeView.Width, e.Bounds.Height); else if((e.State & TreeNodeStates.Selected) != 0) graphics.FillRectangle(SystemBrushes.Highlight, rectX, e.Bounds.Y, m_treeView.Width, e.Bounds.Height); CharacterRange[] ranges = new CharacterRange[1]; ranges[0].First = 0; StringFormat format = new StringFormat(StringFormatFlags.MeasureTrailingSpaces); int offset = 0; float drawPos = e.Bounds.X; foreach(Match m in matches) { if(m.Index != offset) { string substr = text.Substring(offset, m.Index - offset); graphics.DrawString(substr, currentFont, currentBrush, drawPos, e.Bounds.Y); ranges[0].Length = substr.Length; format.SetMeasurableCharacterRanges(ranges); var regions = graphics.MeasureCharacterRanges(substr, currentFont, new RectangleF(0, 0, 1000, 1000), format); var rect = regions[0].GetBounds(graphics); drawPos += rect.Width; } offset = m.Index + m.Length; int index = int.Parse(m.Groups[1].Value); currentFont = fontSet.Fonts[index]; if((e.State & TreeNodeStates.Selected) == 0) currentBrush = fontSet.Brushes[index]; } string final = text.Substring(offset); graphics.DrawString(final, currentFont, currentBrush, drawPos, e.Bounds.Y); }
private static bool SubRange(CharacterRange r1, CharacterRange r2) { return (r1.Left >= r2.Left && r1.Right <= r2.Right); }
private void m_treeView_DrawNode(object sender, DrawTreeNodeEventArgs e) { NodeData data = e.Node.Tag as NodeData; if (data == null) { e.DrawDefault = true; return; } string text = data.FormattedText; var graphics = e.Graphics; Font currentFont = e.Node.NodeFont ?? e.Node.TreeView.Font; Brush currentBrush = (e.State & TreeNodeStates.Selected) != 0 ? Brushes.White : Brushes.Black; FontSet fontSet = IsFiltered(data.Name) ? m_filteredFonts : m_normalFonts; var matches = m_regex.Matches(text); if (matches.Count == 0) { e.DrawDefault = true; return; } bool parentSelected = e.Node.Parent != null && e.Node.Parent.IsSelected; int rectX = e.Bounds.X > 0 ? e.Bounds.X : 0; if (parentSelected) { graphics.FillRectangle(Brushes.AliceBlue, rectX, e.Bounds.Y, m_treeView.Width, e.Bounds.Height); } else if ((e.State & TreeNodeStates.Selected) != 0) { graphics.FillRectangle(SystemBrushes.Highlight, rectX, e.Bounds.Y, m_treeView.Width, e.Bounds.Height); } CharacterRange[] ranges = new CharacterRange[1]; ranges[0].First = 0; StringFormat format = new StringFormat(StringFormatFlags.MeasureTrailingSpaces); int offset = 0; float drawPos = e.Bounds.X; foreach (Match m in matches) { if (m.Index != offset) { string substr = text.Substring(offset, m.Index - offset); graphics.DrawString(substr, currentFont, currentBrush, drawPos, e.Bounds.Y); ranges[0].Length = substr.Length; format.SetMeasurableCharacterRanges(ranges); var regions = graphics.MeasureCharacterRanges(substr, currentFont, new RectangleF(0, 0, 1000, 1000), format); var rect = regions[0].GetBounds(graphics); drawPos += rect.Width; } offset = m.Index + m.Length; int index = int.Parse(m.Groups[1].Value); currentFont = fontSet.Fonts[index]; if ((e.State & TreeNodeStates.Selected) == 0) { currentBrush = fontSet.Brushes[index]; } } string final = text.Substring(offset); graphics.DrawString(final, currentFont, currentBrush, drawPos, e.Bounds.Y); }
public CharRange() { Range = new CharacterRange(); }
//Return Width private float MyDrawString(string text, Graphics g, Brush br, Font font, ref float x, ref float y, bool measure, bool continuousDraw) { float width = 0; if (continuousDraw) { SizeF sz = g.MeasureString(text, font); width = sz.Width; if (!measure) { g.DrawString(text, font, br, x, y); } x += sz.Width; y += sz.Height; } else { int numChars = text.Length; List <string> lst = new List <string>(); if (numChars < 32) { lst.Add(text); } else { int i = 0; int j = 30; for (; i < numChars - j; i += j) { lst.Add(text.Substring(i, j)); } if (i < numChars) { lst.Add(text.Substring(i, numChars - i)); } } float xx = x; foreach (string str in lst) { numChars = str.Length; CharacterRange[] characterRanges = new CharacterRange[numChars]; for (int i = 0; i < numChars; i++) { characterRanges[i] = new CharacterRange(i, 1); } StringFormat stringFormat = new StringFormat { // Make sure the characters are not clipped FormatFlags = StringFormatFlags.NoClip, Alignment = StringAlignment.Center }; stringFormat.SetMeasurableCharacterRanges(characterRanges); Region[] stringRegions = new Region[numChars]; SizeF size = g.MeasureString(str, font); RectangleF layoutRect = new RectangleF(xx + width, y, size.Width, size.Height); stringRegions = g.MeasureCharacterRanges( str, font, layoutRect, stringFormat); for (int indx = 0; indx < numChars; indx++) { Region region = stringRegions[indx]; RectangleF rect = region.GetBounds(g); if (indx == 0) { x = rect.X; y = rect.Y; } x += rect.Width; width += rect.Width; if (!measure) { g.DrawString(str.Substring(indx, 1), font, br, rect, stringFormat); } } } } return(width); }
public void PrepareBatch() { if (glyphCache == null) { glyphCache = GlyphCache.GetCache(Height); } // Add All Glyphs foreach (Text3d t3d in Items) { foreach (char c in t3d.Text) { glyphCache.AddGlyph(c); } } // Calculate Metrics TextObject.Text = ""; TextObject.FontSize = (float)Height * .50f; System.Drawing.Font font = TextObject.Font; StringFormat sf = new StringFormat(); sf.Alignment = StringAlignment.Near; Bitmap bmp = new Bitmap(20, 20); Graphics g = Graphics.FromImage(bmp); // Create Index Buffers List <PositionColoredTextured> verts = new List <PositionColoredTextured>(); foreach (Text3d t3d in Items) { float fntAdjust = font.Size / 128f; String text = t3d.Text; SizeF size = g.MeasureString(text, font); float factor = .6666f; t3d.width = size.Width * (float)t3d.scale * factor; t3d.height = size.Height * (float)t3d.scale * factor; float left = 0; int charsLeft = text.Length; int index = 0; // SetMeasurableCharacterRanges has a limit of 32 items per call; while (charsLeft > 0) { int charsNow = Math.Min(32, charsLeft); charsLeft -= charsNow; CharacterRange[] ranges = new CharacterRange[charsNow]; for (int i = 0; i < charsNow; i++) { ranges[i] = new CharacterRange(i + index, 1); } sf.SetMeasurableCharacterRanges(ranges); Region[] reg = g.MeasureCharacterRanges(text, font, new RectangleF(new PointF(0, 0), size), sf); for (int i = 0; i < (charsNow); i++) { GlyphItem item = glyphCache.GetGlyphItem(text[i + index]); RectangleF rectf = reg[i].GetBounds(g); RectangleF position = new RectangleF(rectf.Left * (float)t3d.scale * factor, rectf.Top * (float)t3d.scale * factor, rectf.Width * (float)t3d.scale * factor, rectf.Height * (float)t3d.scale * factor); position = new RectangleF(left * (float)t3d.scale * factor, 0 * (float)t3d.scale * factor, item.Extents.Width * fntAdjust * (float)t3d.scale * factor, item.Extents.Height * fntAdjust * (float)t3d.scale * factor); left += item.Extents.Width * fntAdjust; t3d.AddGlyphPoints(verts, item.Size, position, item.UVRect); } index += charsNow; } } g.Dispose(); GC.SuppressFinalize(g); bmp.Dispose(); font.Dispose(); vertCount = verts.Count; vertexBuffer = new PositionColorTexturedVertexBuffer11(vertCount, RenderContext11.PrepDevice); PositionColoredTextured[] vertBuf = (PositionColoredTextured[])vertexBuffer.Lock(0, 0); // Lock the buffer (which will return our structs) for (int i = 0; i < vertCount; i++) { vertBuf[i] = verts[i]; } vertexBuffer.Unlock(); glyphVersion = glyphCache.Version; }
int ComputeHashCode() { return(HashCode.Compute( CharacterRange.GetHashCode(), CharacterClass.GetHashCode())); }
public void SetMeasurableCharacterRanges(CharacterRange[] ranges) { }
public override string ToString() { return(CharacterRange.ToString()); }
/// <summary> /// Measures the location of an arbritrary # of words within a string /// </summary> private float[] 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) float[] sz = new float[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); float[] 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++] = pos[j] + startPos; } startPos = sz[icra - 1]; // 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); float[] 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++] = pos[j] + startPos; } } return(sz); }
// Measure the characters in a string with no more than 32 characters. //More than 32 >> Overflow Exception private List<RectangleF> MeasureCharactersInWord(Graphics gr, RectangleF rf, Font font, string text) { List<RectangleF> result = new List<RectangleF>(); using (StringFormat string_format = new StringFormat()) { string_format.Alignment = StringAlignment.Near; string_format.LineAlignment = StringAlignment.Near; string_format.Trimming = StringTrimming.None; string_format.FormatFlags = StringFormatFlags.MeasureTrailingSpaces; CharacterRange[] ranges = new CharacterRange[text.Length]; for (int i = 0; i < text.Length; i++) { ranges[i] = new CharacterRange(i, 1); } string_format.SetMeasurableCharacterRanges(ranges); // Find the character ranges. Region[] regions = gr.MeasureCharacterRanges(text, font, rf, string_format); // Convert the regions into rectangles. foreach (Region region in regions) result.Add(region.GetBounds(gr)); } return result; }
/// <summary> /// Recalculates size of the control /// </summary> /// <param name="MaintainCenter">Wheather position of the center should be maintained, otherwise maintains UpperLeft</param> private void RecalculateSize(bool MaintainCenter) { Size oldSize = Size; Size newSize; Graphics g = this.CreateGraphics(); if (!_Letterwise)//whole string is rotated { if (!base.AutoSize) { return;//if autosizing is not set, no work needed } SizeF measured_size = g.MeasureString(Text, Font); newSize = new Size(Convert.ToInt32(Math.Ceiling(measured_size.Width + Math.Abs(ShadowOffset.X))),//Math.Abs(ShadowOffset Convert.ToInt32(Math.Ceiling(measured_size.Height + Math.Abs(ShadowOffset.Y)))); int d = Convert.ToInt32(Math.Ceiling(Math.Sqrt(newSize.Width * newSize.Width + newSize.Height * newSize.Height)));//d=√(w²+h²) //size (calculated below) can be vastly improved (currently, it allmost allways oversizes control) if (newSize.Width == 0) { newSize = new Size(newSize.Height, 1); //must be non-null in order to calcualte arcus tangent } double d_angle = Math.Atan((double)newSize.Height / newSize.Width); //angle between diagonal and x-axis double r_angle = Math.Max(Math.Abs(-d_angle + _MinRotate * Math.PI / 180.0), Math.Abs(d_angle + _MaxRotate * Math.PI / 180.0)); //maximum rotational angle newSize = new Size(d, Convert.ToInt32(Math.Ceiling(d * Math.Sin(Math.Min(Math.PI / 2, r_angle + d_angle))))); } else//each character is rotated independently { SizeF W = g.MeasureString("W", Font);//single character dimensions SizeF measured_size = g.MeasureString(Text, Font); newSize = new Size(Convert.ToInt32(Math.Ceiling(measured_size.Width + Math.Abs(ShadowOffset.X) + W.Height * 0.5)), Convert.ToInt32(Math.Ceiling(measured_size.Height + Math.Abs(ShadowOffset.Y) + W.Height * 0.5))); //calculate size of each character (which is used in OnPaint) //do it here once, and use it many times in OnPaint SizeF A_A = g.MeasureString("A A", Font, new SizeF(newSize.Width, newSize.Height), StringFormat.GenericTypographic); SizeF AA = g.MeasureString("AA", Font, new SizeF(newSize.Width, newSize.Height), StringFormat.GenericTypographic); spaceSize = new SizeF(A_A.Width - AA.Width, A_A.Height); charSizes = new RectangleF[Text.Length];//allocate it CharacterRange[] cr = new CharacterRange[1]; StringFormat stringFormat = new StringFormat(StringFormat.GenericTypographic); Region[] r; cr[0] = new CharacterRange(0, 1); for (int i = 0; i < Text.Length; i++) { stringFormat.SetMeasurableCharacterRanges(cr); r = g.MeasureCharacterRanges(Text[i].ToString(), Font, new RectangleF(0, 0, newSize.Width, newSize.Height), stringFormat); charSizes[i] = r[0].GetBounds(g); r[0].Dispose(); } stringFormat.Dispose(); } if (base.AutoSize) { Size = newSize; if (MaintainCenter) { Left += (oldSize.Width - newSize.Width) / 2; Top += (oldSize.Height - newSize.Height) / 2; } } g.Dispose(); Refresh(); }
internal static pTexture CreateText(string text, float size, Vector2 restrictBounds, Color color, ShadowType shadow, bool bold, bool italic, bool underline, TextAlignment alignment, bool forceAa, out Vector2 measured, out RectangleF[] characterRegions, Color background, Color border, int borderWidth, bool measureOnly, bool getCharacterRegions, FontFace fontFace, Vector4 cornerBounds, Vector2 padding, pTexture lastTexture = null, int startIndex = 0, int length = -1) { characterRegions = null; if (text == null) { measured = Vector2.Zero; return(null); } if (ConfigManager.dDisableTextRendering) { measured = new Vector2(text.Length * size, size); return(null); } #if DEBUG if (!text.Contains(@"NativeText")) { int limit_per_second = osu.GameModes.Play.Player.Playing ? 5 : 58; bool newSecond = GameBase.Time / 1000 != currentSecond; drawCount++; if (drawCount == limit_per_second) { Debug.Print(@"NativeText: High number of text refreshes per second."); } if (newSecond) { currentSecond = GameBase.Time / 1000; drawCount = 0; } } #endif //This lock ensures we are only using the shared GDI+ object (FromHwnd) in one place at a time. lock (createTextLock) { try { using (System.Drawing.Graphics graphics = System.Drawing.Graphics.FromHwnd(IntPtr.Zero)) using (StringFormat sf = new StringFormat()) { if (dpiRatio == 0) { dpiRatio = 96 / graphics.DpiX; } size *= dpiRatio; GameBase.PerformanceMonitor.ReportCount(CounterType.NativeText); graphics.TextRenderingHint = TextRenderingHint.AntiAlias; SizeF measuredSize; string face = GetFontFace(fontFace); if (face.StartsWith(@"Aller")) { //if we are using the default osu! font, allow specific language overrides based on simple detection. string fontFaceOverride = getLanguageSpeicificFont(text); if (fontFaceOverride != null) { face = fontFaceOverride; } } if (startIndex != 0 || length > 0) { text = text.Substring(startIndex, length); } else if (length == -1) { length = text.Length; } if (size < 20 && face.EndsWith(@" Light")) { face = face.Replace(@" Light", string.Empty); } FontStyle fs = FontStyle.Regular; if (bold) { if (face.EndsWith(@" Light")) { face = face.Replace(@" Light", string.Empty); } fs |= FontStyle.Bold; } if (italic) { fs |= FontStyle.Italic; } if (underline) { fs |= FontStyle.Underline; } switch (alignment) { case TextAlignment.Left: case TextAlignment.LeftFixed: sf.Alignment = StringAlignment.Near; break; case TextAlignment.Centre: sf.Alignment = StringAlignment.Center; break; case TextAlignment.Right: sf.Alignment = StringAlignment.Far; break; } if (!OsuMain.IsWine && face.StartsWith(@"Aller")) { for (char c = '0'; c <= '9'; c++) { text = text.Replace(c, (char)(c + (0xf83c - '0'))); } } Font f = GetFont(face, size * ScaleModifier, fs); if (ScaleModifier != 1) { restrictBounds *= ScaleModifier; } try { if (text.Length == 0) { text = " "; } measuredSize = restrictBounds != Vector2.Zero ? graphics.MeasureString(text, f, new SizeF(restrictBounds.X, restrictBounds.Y), sf) : graphics.MeasureString(text, f); } catch (InvalidOperationException) { measured = Vector2.Zero; return(null); } int width = (int)(measuredSize.Width + 1); int height = (int)(measuredSize.Height + 1); if (restrictBounds.Y != 0) { height = (int)restrictBounds.Y; } if (restrictBounds.X != 0 && (alignment != TextAlignment.Left || background.A > 0)) { width = (int)restrictBounds.X; } if (padding != Vector2.Zero && restrictBounds == Vector2.Zero) { width += (int)(padding.X * 2); height += (int)(padding.Y * 2); } measured = new Vector2(width, height); float offset = Math.Max(0.5f, Math.Min(1f, (size * ScaleModifier) / 14)); if (getCharacterRegions) { characterRegions = new RectangleF[text.Length]; // SetMeasurableCharacterRanges only accepts a maximum of 32 intervals to be queried, so we as the library user are // forced to split the string into 32 character long chunks and perform MeasureCharacterRanges on each. int numIntervals = (text.Length / 32) + 1; for (int i = 0; i < numIntervals; ++i) { int offsetIndex = i * 32; int end = Math.Min(text.Length - offsetIndex, 32); CharacterRange[] characterRanges = new CharacterRange[end]; for (int j = 0; j < end; ++j) { characterRanges[j] = new CharacterRange(j + offsetIndex, 1); } sf.SetMeasurableCharacterRanges(characterRanges); Region[] regions = graphics.MeasureCharacterRanges( text, f, new RectangleF( padding.X, padding.Y, restrictBounds.X == 0 ? Single.PositiveInfinity : restrictBounds.X, restrictBounds.Y == 0 ? Single.PositiveInfinity : restrictBounds.Y), sf); for (int j = 0; j < end; ++j) { Region region = regions[j] as Region; characterRegions[j + offsetIndex] = region.GetBounds(graphics); } } } if (measureOnly) { int startSpace = 0; int endSpace = 0; int i = 0; while (i < text.Length && text[i++] == ' ') { startSpace++; } int j = text.Length - 1; while (j >= i && text[j--] == ' ') { endSpace++; } if (startSpace == text.Length) { endSpace += startSpace; } measured = new Vector2(width + (endSpace * 5.145f * size / 12), height); return(null); } using (Bitmap b = new Bitmap(width, height, PixelFormat.Format32bppArgb)) using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(b)) { //Quality settings g.TextRenderingHint = graphics.TextRenderingHint; g.SmoothingMode = SmoothingMode.HighQuality; g.InterpolationMode = InterpolationMode.HighQualityBicubic; if (background.A > 0) { if (cornerBounds != Vector4.Zero) { fillRoundedRectangle(g, new Rectangle(0, 0, width, height), new SolidBrush(OsuMathHelper.CConvert(background)), cornerBounds); if (borderWidth > 0) { drawRoundedRectangle(g, new Rectangle(0, 0, width - (int)Math.Ceiling(borderWidth / 2f), height - (int)Math.Ceiling(borderWidth / 2f)), new Pen(OsuMathHelper.CConvert(border), borderWidth), cornerBounds); } } else { g.Clear(OsuMathHelper.CConvert(background)); if (borderWidth > 0) { g.DrawRectangle(new Pen(OsuMathHelper.CConvert(border), borderWidth), new Rectangle(borderWidth / 2, borderWidth / 2, width - borderWidth, height - borderWidth)); } } } else { g.Clear(System.Drawing.Color.FromArgb(1, color.R, color.G, color.B)); } using (Brush brush = new SolidBrush(OsuMathHelper.CConvert(color))) { if (restrictBounds != Vector2.Zero) { restrictBounds.X -= padding.X * 2; restrictBounds.Y -= padding.Y * 2; switch (shadow) { case ShadowType.Normal: g.DrawString(text, f, shadowBrush, new RectangleF(padding.X - offset, offset + padding.Y, restrictBounds.X, restrictBounds.Y), sf); g.DrawString(text, f, shadowBrush, new RectangleF(padding.X + offset, offset + padding.Y, restrictBounds.X, restrictBounds.Y), sf); break; case ShadowType.Border: Brush borderBrush = greyBrush; if (background.A == 0 && borderWidth == 1 && border.A > 0) { borderBrush = new SolidBrush(OsuMathHelper.CConvert(border)); } g.DrawString(text, f, borderBrush, new RectangleF(padding.X + offset, padding.Y + offset, restrictBounds.X, restrictBounds.Y), sf); g.DrawString(text, f, borderBrush, new RectangleF(padding.X + offset, padding.Y - offset, restrictBounds.X, restrictBounds.Y), sf); g.DrawString(text, f, borderBrush, new RectangleF(padding.X - offset, padding.Y + offset, restrictBounds.X, restrictBounds.Y), sf); g.DrawString(text, f, borderBrush, new RectangleF(padding.X - offset, padding.Y - offset, restrictBounds.X, restrictBounds.Y), sf); break; } g.DrawString(text, f, brush, new RectangleF(padding.X, padding.Y, restrictBounds.X, restrictBounds.Y), sf); } else { switch (shadow) { case ShadowType.Normal: g.DrawString(text, f, shadowBrush, padding.X - offset, padding.Y + offset); g.DrawString(text, f, shadowBrush, padding.X + offset, padding.Y + offset); break; case ShadowType.Border: Brush borderBrush = greyBrush; if (background.A == 0 && borderWidth == 1 && border.A > 0) { borderBrush = new SolidBrush(OsuMathHelper.CConvert(border)); } g.DrawString(text, f, borderBrush, padding.X + offset, padding.Y + offset); g.DrawString(text, f, borderBrush, padding.X - offset, padding.Y + offset); g.DrawString(text, f, borderBrush, padding.X + offset, padding.Y - offset); g.DrawString(text, f, borderBrush, padding.X - offset, padding.Y - offset); break; } g.DrawString(text, f, brush, padding.X, padding.Y); } } //if (lastTexture == null || lastTexture.isDisposed) { lastTexture = pTexture.FromBitmap(b); lastTexture.Disposable = true; } /*else * { * lastTexture.Width = b.Width; * lastTexture.Height = b.Height; * lastTexture.SetData(b); * }*/ return(lastTexture); } } } catch (Exception e) { measured = Vector2.Zero; return(null); } } }
public FooterMapping(ConversionContext ctx, FooterPart part, CharacterRange ftr) : base(ctx, part) { this._ftr = ftr; }
private void lbResults_DrawItem(object sender, DrawItemEventArgs e) { e.DrawBackground(); bool selected = (e.State & DrawItemState.Selected) == DrawItemState.Selected; if ((e.Index < 0) || (e.Index >= SearchResults.Count)) return; var search = ActiveSearchQuery; if (search == null) return; using (var backgroundBrush = new SolidBrush(selected ? SystemColors.Highlight : lbResults.BackColor)) using (var brush = new SolidBrush(selected ? SystemColors.HighlightText : lbResults.ForeColor)) { var item = SearchResults[e.Index]; var format = StringFormat.GenericTypographic; format.LineAlignment = StringAlignment.Near; format.FormatFlags = StringFormatFlags.NoWrap; format.Trimming = StringTrimming.EllipsisPath; format.Alignment = StringAlignment.Near; var rect = new RectangleF(e.Bounds.X, e.Bounds.Y + 1, e.Bounds.Width - LineNumberWidth, LineHeight); e.Graphics.DrawString(item.Filename, lbResults.Font, brush, rect, format); format.Trimming = StringTrimming.Character; format.Alignment = StringAlignment.Far; rect = new RectangleF(e.Bounds.X, e.Bounds.Y + 1, e.Bounds.Width, LineHeight); e.Graphics.DrawString(item.LineNumber.ToString(), lbResults.Font, brush, rect, format); string context = item.Context; MatchEvaluator blankEvaluator = (m) => new String(' ', m.Length); string cleanContext = search.Regex.Replace(item.Context, blankEvaluator); format.Trimming = StringTrimming.None; format.Alignment = StringAlignment.Near; rect = new RectangleF(e.Bounds.X + 6, e.Bounds.Y + LineHeight + 1, e.Bounds.Width - 6, e.Bounds.Height - LineHeight); using (var pen = new Pen(SystemColors.ButtonShadow, 1.0f)) e.Graphics.DrawLine(pen, rect.Location, new PointF(rect.Right, rect.Top)); e.Graphics.DrawString(cleanContext, lbResults.Font, brush, rect, format); using (var maskBrush = new SolidBrush(Color.FromArgb(127, selected ? SystemColors.Highlight : lbResults.BackColor))) { var mrect = new RectangleF(e.Bounds.X + 6, e.Bounds.Y + LineHeight + 1, e.Bounds.Width - 6, LineHeight); e.Graphics.FillRectangle(maskBrush, mrect); mrect = new RectangleF(e.Bounds.X + 6, e.Bounds.Y + (LineHeight * 3) + 1, e.Bounds.Width - 6, LineHeight); e.Graphics.FillRectangle(maskBrush, mrect); } var matches = search.Regex.Matches(context); if (matches.Count > 0) { var ranges = (from m in matches.Cast<Match>() select new CharacterRange(m.Index, m.Length)).ToArray(); int blockSize = Math.Min(32, ranges.Length); var temp = new CharacterRange[blockSize]; e.Graphics.ResetClip(); e.Graphics.ExcludeClip(e.Graphics.Clip); for (int i = 0; i < ranges.Length; i += 32) { Array.Copy(ranges, i, temp, 0, Math.Min(blockSize, ranges.Length - i)); format.SetMeasurableCharacterRanges(temp); foreach (var region in e.Graphics.MeasureCharacterRanges(item.Context, lbResults.Font, rect, format)) e.Graphics.SetClip(region, System.Drawing.Drawing2D.CombineMode.Union); } using (var highlightBrush = new SolidBrush(SystemColors.Highlight)) using (var highlightTextBrush = new SolidBrush(SystemColors.HighlightText)) { e.Graphics.FillRectangle(highlightBrush, rect); e.Graphics.DrawString(context, lbResults.Font, highlightTextBrush, rect, format); } e.Graphics.ResetClip(); } } e.DrawFocusRectangle(); }
/// <summary> /// Finds an identifier in visible text context /// </summary> /// <param name="index"></param> /// <param name="identifierRange"></param> /// <param name="visibleRange"></param> /// <param name="visibleText"></param> /// <returns></returns> private string FindIdentifierAt(int index, out CharacterRange identifierRange, out CharacterRange visibleRange, out string visibleText) { visibleRange = GetVisibleRange(); visibleText = GetTextRange(visibleRange.First, visibleRange.Length); index -= visibleRange.First; if (index < 0) { identifierRange = default(CharacterRange); return null; } var start = FindIdentifierStart(visibleText, index); var end = FindIdentifierEnd(visibleText, index); if (start < 0 || end < 0 || end < start) { identifierRange = default(CharacterRange); return null; } identifierRange = new CharacterRange(start + visibleRange.First, end - start + 1); return visibleText.Substring(start, end - start + 1); }
// Gets the bounds of each character in a line of text. // The line is processed in blocks of 32 characters (GdiPlus.MaxMeasurableCharacterRanges). IEnumerable<RectangleF> GetCharExtents(string text, int height, int line_start, int line_length, RectangleF layoutRect, IntPtr native_graphics, IntPtr native_font, IntPtr native_string_format) { RectangleF rect = new RectangleF(); int line_end = line_start + line_length; while (line_start < line_end) { //if (text[line_start] == '\n' || text[line_start] == '\r') //{ // line_start++; // continue; //} int num_characters = (line_end - line_start) > GdiPlus.MaxMeasurableCharacterRanges ? GdiPlus.MaxMeasurableCharacterRanges : line_end - line_start; int status = 0; for (int i = 0; i < num_characters; i++) { characterRanges[i] = new CharacterRange(line_start + i, 1); IntPtr region; status = GdiPlus.CreateRegion(out region); regions[i] = region; Debug.Assert(status == 0, String.Format("GDI+ error: {0}", status)); } status = GdiPlus.SetStringFormatMeasurableCharacterRanges(native_string_format, num_characters, characterRanges); Debug.Assert(status == 0, String.Format("GDI+ error: {0}", status)); status = GdiPlus.MeasureCharacterRanges(native_graphics, text, text.Length, native_font, ref layoutRect, native_string_format, num_characters, regions); Debug.Assert(status == 0, String.Format("GDI+ error: {0}", status)); for (int i = 0; i < num_characters; i++) { GdiPlus.GetRegionBounds(regions[i], native_graphics, ref rect); Debug.Assert(status == 0, String.Format("GDI+ error: {0}", status)); GdiPlus.DeleteRegion(regions[i]); Debug.Assert(status == 0, String.Format("GDI+ error: {0}", status)); rect.Y += height; yield return rect; } line_start += num_characters; } }
public TextRange(CharacterRange chrRange, int stringCapacity) { _sciTextRange.chrg = chrRange; _sciTextRange.lpstrText = Marshal.AllocHGlobal(stringCapacity); }
/// <summary> /// Parses any inline code within the specified <paramref name="text"/>. /// </summary> /// <param name="text">The text to parse.</param> /// <param name="sourceFilePath">The path of the source file.</param> /// <exception cref="ArgumentNullException">The specified <paramref name="text"/> is <c>null</c>.</exception> private void Parse(string text, string sourceFilePath) { if (text == null) { throw new ArgumentNullException("text"); } inputText = text; lock (regexLock) { char[] inputChars = inputText.ToCharArray(); // Disable all scripted remark sections while leaving the character locations // within the document intact. This way the line numbers in the source file // references will remain correct. foreach (Match match in remarksRegex.Matches(inputText)) { int startIndex = match.Index + Constants.ScriptStartMarker.Length; int endIndex = match.Index + match.Length - Constants.ScriptEndMarker.Length; for (int i = startIndex; i < endIndex; i++) { if (!char.IsControl(inputText[i])) { inputChars[i] = '\0'; } } } inputText = new string(inputChars); // Determine the character range for each line. Dictionary<int, CharacterRange> lineMap = new Dictionary<int, CharacterRange>(); int lineNumber = 1; int characterIndex = 0; string[] lines = inputText.Split(new char[] { '\n' }); for (int i = 0; i < lines.Length; i++) { if (lines[i].Length > 0) { lines[i] = lines[i].Substring(0, lines[i].Length - 1); } } inputText = string.Join( string.Empty, lines.Select((n, idx) => ((n.TrimStart().StartsWith(Constants.ScriptStartMarker, StringComparison.Ordinal) && !n.TrimStart().StartsWith(Constants.ScriptStartMarker + Constants.ScriptAutoWriteMarker, StringComparison.Ordinal) && n.TrimEnd().EndsWith(Constants.ScriptEndMarker)) || idx == lines.Length - 1) ? n : n + "\r\n")); for (int i = 0; i < lines.Length; i++) { string line = lines[i]; int length = line.Length + ((i < lines.Length - 1) ? 1 : 0); lineMap[lineNumber++] = new CharacterRange() { Offset = characterIndex, Length = length }; characterIndex += length; } // Parse all fragments. int index = 0; string[] fragments = scriptsRegex.Split(inputText); foreach (string fragment in fragments) { if (!fragment.Equals(Constants.ScriptStartMarker, StringComparison.Ordinal) && !fragment.Equals(Constants.ScriptEndMarker, StringComparison.Ordinal)) { ParseFragment( fragment, lineMap.First(n => index >= n.Value.Offset && index < n.Value.Offset + n.Value.Length).Key, sourceFilePath); } index += fragment.Length; } } }
private static bool InRange(char c, CharacterRange range) { return (c >= range.Left && c <= range.Right); }
private bool DrawStrings(string text, Rectangle bounds, Graphics graphics, Color color, Regex regex, string groupName) { if (!regex.IsMatch(text)) return false; MatchCollection matches = regex.Matches(text); bool result = false; foreach (Match match in matches) { using (SolidBrush brush = new SolidBrush(color)) { foreach (Capture capture in match.Groups[groupName].Captures) { // create a character range for the capture CharacterRange[] characterRanges = new CharacterRange[] { new CharacterRange(capture.Index, capture.Length)}; // create a new string format, using the default one as a prototype StringFormat stringFormat = new StringFormat(_stringFormat); stringFormat.SetMeasurableCharacterRanges(characterRanges); // measure the character ranges for the capture, getting an array of regions Region[] regions = new Region[1]; regions = graphics.MeasureCharacterRanges(text, this.Font, bounds, stringFormat); // Draw each measured string within each region. foreach (Region region in regions) { RectangleF rectangle = region.GetBounds(graphics); graphics.DrawString(capture.Value, this.Font, brush, rectangle, _stringFormat); // draw character range bounding rectangles, for troubleshooting only if (_displayCharacterRangeBounds) using (Pen pen = new Pen(brush.Color)) graphics.DrawRectangle(pen, rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height); result = true; } } } } return result; }
private static bool Overlaps(CharacterRange r1, CharacterRange r2) { return (r1.Left <= r2.Right && r1.Right > r2.Right); }
public void SetMeasurableCharacterRanges(CharacterRange [] ranges) { throw new NotImplementedException (); }
static Tuple <CharacterRange, CharacterRange> SectionToCurves(List <PointF> path, CharacterRange sectionRange, int maxPtNum, float maxAngle) { if (sectionRange.Length <= 0 || path == null || path.Count < 5 || maxPtNum < 3) { return(null); } float cos = (float)Math.Cos(maxAngle); //------------------------------------------------------ int start1 = sectionRange.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[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); } //------------------------------------------------------ int start2 = sectionRange.First + sectionRange.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)); }