/// <summary> /// Creates a new instance. /// </summary> internal PropView(View other) : base(other) { _Layout = new PropTextLayout(this); // Release selection (because changing view while keeping selection makes pretty // difficult problem around invalidation) if (Document != null) { Document.SetSelection(Document.CaretIndex, Document.CaretIndex); } }
public void DrawLineMarker(Point pos, ITextLayout layout) { if (this.HideLineMarker) { return; } IEditorRender render = (IEditorRender)base.render; Point p = this.CaretLocation; double height = layout.Height; double width = this.render.TextArea.Width; render.FillRectangle(new Rectangle(this.PageBound.X + this.render.TextArea.X, pos.Y, width, height), FillRectType.LineMarker); }
private PlacedBitmap CreateFontPreview(string gdiFontName, float fontSize, PaintDotNet.UI.Media.Brush textBrush) { FontProperties fontProperties; TextMetrics metrics; OverhangMetrics overhangMetrics; try { fontProperties = this.fontMap.GetFontProperties(gdiFontName); using (IDrawingContext context = DrawingContext.CreateNull(FactorySource.PerThread)) { TextLayoutAlgorithm?layoutAlgorithm = null; TextLayout resourceSource = UIText.CreateLayout(context, this.fontSampleText, fontProperties, (double)fontSize, layoutAlgorithm, HotkeyRenderMode.Ignore, 65535.0, 65535.0); ITextLayout cachedOrCreateResource = context.GetCachedOrCreateResource <ITextLayout>(resourceSource); metrics = cachedOrCreateResource.Metrics; overhangMetrics = cachedOrCreateResource.OverhangMetrics; } } catch (Exception exception) { if ((!(exception is NoFontException) && !(exception is FontFileAccessException)) && (!(exception is FontFileFormatException) && !(exception is FontFileNotFoundException))) { throw; } Surface cleanupObject = Surface.CopyFromGdipImage(PdnResources.GetImageResource("Icons.WarningIcon.png").Reference); BitmapProxy proxy = new BitmapProxy(cleanupObject.CreateAliasedImagingBitmap(), ObjectRefProxyOptions.AssumeOwnership); proxy.AddCleanupObject(cleanupObject); return(new PlacedBitmap(proxy, new RectDouble(0.0, 0.0, (double)proxy.Size.Width, (double)proxy.Size.Height), true)); } RectDouble a = new RectDouble((double)metrics.Left, (double)metrics.Top, (double)(metrics.Left + metrics.WidthMax), (double)(metrics.Top + metrics.Height)); RectDouble b = RectDouble.FromEdges((double)(metrics.Left - overhangMetrics.Left), (double)(metrics.Top - overhangMetrics.Top), (double)(metrics.LayoutWidth + overhangMetrics.Right), (double)(metrics.LayoutHeight + overhangMetrics.Bottom)); RectInt32 num4 = RectDouble.Union(a, b).Int32Bound; IBitmap bitmap = new PaintDotNet.Imaging.Bitmap(num4.Width, num4.Height, PixelFormats.Pbgra32, BitmapCreateCacheOption.CacheOnLoad); using (IDrawingContext context2 = DrawingContext.FromBitmap(bitmap, FactorySource.PerThread)) { context2.Clear(null); using (context2.UseTranslateTransform((float)-num4.X, (float)-num4.Y, MatrixMultiplyOrder.Prepend)) { using (context2.UseTextRenderingMode(TextRenderingMode.Outline)) { TextLayout textLayout = UIText.CreateLayout(context2, this.fontSampleText, fontProperties, (double)fontSize, null, HotkeyRenderMode.Ignore, 65535.0, 65535.0); context2.TextAntialiasMode = TextAntialiasMode.Grayscale; context2.DrawTextLayout(0.0, 0.0, textLayout, textBrush, DrawTextOptions.None); } } } return(new PlacedBitmap(bitmap, b, true)); }
protected override void CreateResources() { string text = "Hello World From ... DirectWrite!"; _blackBrush = RenderTarget.CreateSolidColorBrush(Color.Black); _textLayout = DirectWriteFactory.CreateTextLayout(text, _textFormat, RenderTarget.GetSize()); // (21, 12) is the range around "DirectWrite!" _textLayout.SetFontSize(100, (21, 12)); _typography = DirectWriteFactory.CreateTypography(); _typography.AddFontFeature(new FontFeature(FontFeatureTag.StylisticSet7, 1)); _textLayout.SetTypography(_typography, (0, text.Length)); _textLayout.SetUnderline(true, (21, 12)); _textLayout.SetFontWeight(FontWeight.Bold, (21, 12)); }
public override void CalculateLineCountOnScreen() { if (this.LayoutLines.Count == 0 || this.PageBound.Height == 0) { return; } double y = 0; int i = this.Src.Row; int visualCount = this.Src.Row; for (; true; i++) { int row = i < this.LayoutLines.Count ? i : this.LayoutLines.Count - 1; int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(row); int lineLength = this.LayoutLines.GetLengthFromLineNumber(row); if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex) && row < this.LayoutLines.Count - 1) { continue; } ITextLayout layout = this.LayoutLines.GetLayout(row); double width = layout.Width; if (width > this._LongestWidth) { this._LongestWidth = width; } double lineHeight = layout.Height; y += lineHeight; if (y >= this.render.TextArea.Height) { break; } visualCount++; } this.LineCountOnScreen = Math.Max(visualCount - this.Src.Row - 1, 0); this.LineCountOnScreenWithInVisible = Math.Max(i - this.Src.Row - 1, 0); }
/// <summary> /// 現在のキャレット位置の領域を返す /// </summary> /// <returns>矩形領域を表すRectangle</returns> public Rectangle GetCurrentCaretRect() { ITextLayout layout = this.LayoutLines.GetLayout(this.Document.CaretPostion.row); double width = layout.GetWidthFromIndex(this.Document.CaretPostion.col); if (width == 0.0) { width = this.CaretWidthOnInsertMode; } double height = this.LayoutLines.GetLineHeight(this.Document.CaretPostion); Rectangle updateRect = new Rectangle( this.CaretLocation.X, this.CaretLocation.Y, width, height); return(updateRect); }
private void OnSectionsListBoxDrawItem(object sender, DrawItemEventArgs e) { SettingsDialogSection section = this.sectionsListBox.Items[e.Index] as SettingsDialogSection; int x = UIUtil.ScaleWidth(4); using (IDrawingContext context = DrawingContextUtil.FromGraphics(e.Graphics, e.Bounds, false, FactorySource.PerThread)) { HighlightState disabled; context.Clear(new ColorRgba128Float?(this.BackColor)); if (e.State.HasFlag(DrawItemState.Disabled) || e.State.HasFlag(DrawItemState.Grayed)) { disabled = HighlightState.Disabled; } else if (e.State.HasFlag(DrawItemState.Selected)) { disabled = HighlightState.Checked; } else if (e.State.HasFlag(DrawItemState.HotLight) || (e.Index == this.hotTrackIndex)) { disabled = HighlightState.Hover; } else { disabled = HighlightState.Default; } RectInt32 bounds = e.Bounds.ToRectInt32(); bounds.Inflate(-1, -1); this.selectionHighlightRenderer.HighlightState = disabled; this.selectionHighlightRenderer.RenderBackground(context, bounds); SizeInt32 num4 = UIUtil.ScaleSize(section.DeviceIcon.PixelSize); RectInt32 num5 = new RectInt32(x, e.Bounds.Top + ((e.Bounds.Height - num4.Height) / 2), num4.Width, num4.Height); context.DrawBitmap(section.DeviceIcon, new RectDouble?(num5), 1.0, BitmapInterpolationMode.Linear, null); HotkeyRenderMode hotkeyRenderMode = !e.State.HasFlag(DrawItemState.NoAccelerator) ? HotkeyRenderMode.Show : HotkeyRenderMode.Hide; TextLayout resourceSource = UIText.CreateLayout(context, section.DisplayName, e.Font, null, hotkeyRenderMode, 65535.0, 65535.0); ITextLayout cachedOrCreateResource = context.GetCachedOrCreateResource <ITextLayout>(resourceSource); int num6 = num5.Right + x; float num7 = e.Bounds.Top + ((e.Bounds.Height - cachedOrCreateResource.Metrics.Height) / 2f); context.DrawTextLayout((double)num6, (double)num7, resourceSource, this.selectionHighlightRenderer.EmbeddedTextBrush, DrawTextOptions.None); if (!e.State.HasFlag(DrawItemState.NoFocusRect)) { context.DrawFocusRectangle(e.Bounds.ToRectFloat()); } } }
private void OnComboBoxDrawItem(object sender, DrawItemEventArgs e) { if (e.Index != -1) { RectInt32 rect = e.Bounds.ToRectInt32(); using (IDrawingContext context = DrawingContextUtil.FromGraphics(e.Graphics, rect, false, FactorySource.PerThread)) { using (context.UseTranslateTransform((float)e.Bounds.X, (float)e.Bounds.Y, MatrixMultiplyOrder.Prepend)) { HighlightState hover; RectInt32 num2 = new RectInt32(0, 0, rect.Width, rect.Height); Item item = (Item)this.comboBox.Items[e.Index]; if ((e.State & DrawItemState.Selected) > DrawItemState.None) { hover = HighlightState.Hover; } else { hover = HighlightState.Default; } Color embeddedTextColor = SelectionHighlight.GetEmbeddedTextColor(hover); context.FillRectangle(num2, PaintDotNet.UI.Media.SystemBrushes.Window); this.selectionHighlightRenderer.HighlightState = hover; this.selectionHighlightRenderer.RenderBackground(context, num2); int extent = 0; if ((item.Image != null) && (item.Image.PixelFormat != System.Drawing.Imaging.PixelFormat.Undefined)) { extent = this.dropShadowRenderer.GetRecommendedExtent(item.Image.Size.ToSizeInt32()); RectInt32 num4 = new RectInt32((this.imageXInset + extent) + ((this.maxImageSize.Width - item.Image.Width) / 2), (this.imageYInset + extent) + ((this.maxImageSize.Height - item.Image.Height) / 2), item.Image.Width, item.Image.Height); context.DrawBitmap(item.DeviceImage, new RectDouble?(num4), 1.0, BitmapInterpolationMode.Linear, null); this.dropShadowRenderer.RenderOutside(context, num4, extent); } TextLayout resourceSource = UIText.CreateLayout(context, item.Name, this.Font, null, HotkeyRenderMode.Ignore, (double)e.Bounds.Width, (double)e.Bounds.Height); ITextLayout cachedOrCreateResource = context.GetCachedOrCreateResource <ITextLayout>(resourceSource); int num5 = ((((this.imageXInset + extent) + this.maxImageSize.Width) + extent) + this.imageXInset) + this.textLeftMargin; int num6 = (this.itemSize.Height - ((int)cachedOrCreateResource.Metrics.Height)) / 2; context.DrawTextLayout((double)num5, (double)num6, resourceSource, this.selectionHighlightRenderer.EmbeddedTextBrush, DrawTextOptions.None); } } } }
bool DrawCaret() { if (this.HideCaret || !this.IsFocused) { return(false); } long diff = DateTime.Now.Ticks - this.tickCount; long blinkTime = this.To100nsTime(this.CaretBlinkTime); if (this.CaretBlink && diff % blinkTime >= blinkTime / 2) { return(false); } Rectangle CaretRect = new Rectangle(); IEditorRender render = (IEditorRender)base.render; int row = this.Document.CaretPostion.row; ITextLayout layout = this.LayoutLines.GetLayout(row); double lineHeight = render.emSize.Height; double charWidth = layout.GetWidthFromIndex(this.Document.CaretPostion.col); if (this.InsertMode || charWidth == 0) { CaretRect.Size = new Size(CaretWidthOnInsertMode, lineHeight); CaretRect.Location = new Point(this.CaretLocation.X, this.CaretLocation.Y); render.FillRectangle(CaretRect, FillRectType.InsertCaret); } else { double height = lineHeight / 3; CaretRect.Size = new Size(charWidth, height); CaretRect.Location = new Point(this.CaretLocation.X, this.CaretLocation.Y + lineHeight - height); render.FillRectangle(CaretRect, FillRectType.OverwriteCaret); } return(true); }
/// <summary> /// Creates a new instance. /// </summary> /// <param name="ui">Implementation of the platform dependent UI module.</param> internal PropWrapView(IUserInterface ui) : base(ui) { _Layout = new PropWrapTextLayout(this); Document.ViewParam.ScrollPosX = 0; }
public static void SetMaxSize(this ITextLayout textLayout, SizeF maxSize) { textLayout.SetMaxHeight(maxSize.Height); textLayout.SetMaxWidth(maxSize.Width); }
public override bool Compose(DrawContext dc, Style c, int availWidth, out ItemMetrics im, bool suppressWhitespace, out ITextLayout next) { TextItemMetrics metrics = new TextItemMetrics(this); im = metrics; this.style = c; next = null; // TODO: L: optimise Size sz = dc.Graphics.MeasureText(" "); spaceWidth = sz.Width; height = sz.Height; width = 0; // get the font ascent ascent = c.FontAscent; if (textNode.NodeType == XmlNodeType.SignificantWhitespace) { // special case, simply set to single space width and return width = sz.Width; len = textNode.Value.Length; metrics.CanBreakBefore = true; metrics.CanBreakAfter = true; return(true); } int startSpaceCount = GetStartSpaceCount(); if (startSpaceCount > 0 && suppressWhitespace) { TrimStart(startSpaceCount); startSpaceCount = 0; } if (startSpaceCount > 1) { TrimStart(startSpaceCount - 1); startSpaceCount = 1; } len = startSpaceCount; if (start + len == textNode.Value.Length) { // this is pure whitespace width = sz.Width; return(true); } metrics.CanBreakBefore = startSpaceCount > 0; bool hasMoreContent = true; bool firstWord = true; bool fit = false; int endSpaceCount = 0; int finalWidth = startSpaceCount * spaceWidth; int splitLen = 0; int splitWidth = 0; bool needNewline = false; // bool newline=false; while (hasMoreContent) { int testLen; int tesc; hasMoreContent = IncludeNextWord(out testLen, out tesc); string segString = textNode.Value.Substring(start + len, testLen - len - tesc); string testString = ProcessText(segString); int segWidth = dc.Graphics.MeasureText(testString).Width; int testWidth = finalWidth + segWidth; // string testString=ProcessText(textNode.Value.Substring(start, testLen-tesc)); // int testWidth=dc.Graphics.MeasureText(testString).Width; fit = testWidth < availWidth; if (fit || firstWord) { // either it fits or it has to fit because this is the first word metrics.AddSegment(start + len, testLen - len, segWidth); splitLen = len; len = testLen; splitWidth = finalWidth; endSpaceCount = tesc; finalWidth = testWidth + (endSpaceCount > 0 ? spaceWidth : 0); if (!fit && firstWord) { needNewline = true; } if (!fit || endSpaceCount > 1) { break; } } else { break; } firstWord = false; } // this is handled by custom class // if ( style.Pre && newline ) // bi.ForceBreakAfter=true; Debug.Assert(len > 0, "Must have laid out something!"); // at this point we have these possibilities: // everything fit - fit == true, nothing to do, return true // not everything fit - fit == false, get next, return false // and cannot split - oldLen=-1, return false // and can split - oldLen > 0, ConfigureSplitInfo, return true metrics.CanBreakAfter = endSpaceCount > 0; width = finalWidth; if (splitLen > 0) { canSplit = true; splitIndex = splitLen; splitLeftWidth = splitWidth; splitRightWidth = finalWidth - splitWidth; } if (start + len < textNode.Value.Length) { next = GetNextFragment(); } if (endSpaceCount > 1) { TrimEnd(endSpaceCount - 1); endSpaceCount = 1; } return(!needNewline); }
public override bool Compose(DrawContext dc, Style c, int width, out ItemMetrics bi, bool suppressWhitespace, out ITextLayout next) { this.style = c; bi = new ItemMetrics(this); next = null; // idea here is just to scan for next line break // TODO: M: may need to deal with double spaces, tabs, etc string text = Text; int ptr = text.IndexOf('\n'); int measureLen = len; if (ptr >= 0) { bi.ForceBreakAfter = true; len = ptr + 1; measureLen = len - 1; if (len < text.Length) { next = GetNextFragment(); } } if (measureLen > 0 && Text[measureLen - 1] == '\r') { measureLen--; } Size sz = dc.Graphics.MeasureText(Text.Substring(0, measureLen)); height = dc.Graphics.GetFontHeight(); this.width = sz.Width; ascent = c.FontAscent; return(true); }
private void DrawComboBoxItem(DrawItemEventArgs e) { HighlightState hover; string fontName = (string)base.ComboBox.Items[e.Index]; bool flag = (e.State & DrawItemState.Selected) > DrawItemState.None; bool flag2 = this.hasBeenShown && (e.Bounds.Width >= (base.ComboBox.DropDownWidth / 2)); if (!flag2) { hover = HighlightState.Default; } else if (flag) { hover = HighlightState.Hover; } else { hover = HighlightState.Default; } Color selectionBackColor = SelectionHighlight.GetSelectionBackColor(hover); int num = UIUtil.ScaleWidth(3); int num2 = num; int num3 = -1; this.selectionHighlightRenderer.HighlightState = hover; using (IDrawingContext context = DrawingContextUtil.FromGraphics(e.Graphics, e.Bounds, false, FactorySource.PerThread)) { RenderLayer layer = new RenderLayer(); context.Clear(new ColorRgba128Float?((ColorRgba128Float)PaintDotNet.Imaging.SystemColors.Window)); this.selectionHighlightRenderer.RenderBackground(context, e.Bounds.ToRectFloat()); SizedFontProperties menu = this.systemFonts.Menu; PaintDotNet.UI.Media.Brush textBrush = this.selectionHighlightRenderer.EmbeddedTextBrush; TextLayout textLayout = UIText.CreateLayout(context, fontName, menu, null, HotkeyRenderMode.Ignore, (double)(e.Bounds.Width - num2), (double)e.Bounds.Height); textLayout.ParagraphAlignment = ParagraphAlignment.Center; textLayout.WordWrapping = WordWrapping.NoWrap; int num5 = num + e.Bounds.X; context.DrawTextLayout((double)num5, (double)(e.Bounds.Y + num3), textLayout, textBrush, DrawTextOptions.None); ITextLayout cachedOrCreateResource = context.GetCachedOrCreateResource <ITextLayout>(textLayout); int num4 = (int)Math.Ceiling((double)(num5 + cachedOrCreateResource.Metrics.WidthMax)); PlacedBitmap bitmap = this.TryGetFontPreview(fontName, 16f, textBrush); if (bitmap == null) { IntPtr listHwnd = UIUtil.GetListBoxHwnd(base.ComboBox); Action callback = delegate { try { PlacedBitmap bitmap = this.GetOrCreateFontPreview(fontName, 16f, textBrush); if (listHwnd != IntPtr.Zero) { this.ComboBox.BeginInvoke(() => UIUtil.InvalidateHwnd(listHwnd)); } } catch (Exception) { } }; if (this.backgroundThread == null) { this.backgroundThread = new ThreadDispatcher(ApartmentState.MTA); } this.backgroundThread.Enqueue(QueueSide.Front, callback).Observe(); } if (flag2 && (bitmap != null)) { PaintDotNet.UI.Media.Brush brush; RectFloat num7; RectFloat num6 = new RectFloat((float)((e.Bounds.Right - num) - bitmap.Bitmap.Size.Width), num3 + ((float)Math.Floor((double)((e.Bounds.Y + ((e.Bounds.Height - bitmap.LayoutRect.Height) / 2.0)) - bitmap.LayoutRect.Top))), (float)bitmap.Bitmap.Size.Width, (float)bitmap.Bitmap.Size.Height); if (num6.Left > num4) { num7 = num6; brush = null; } else { num7 = num6; num7.X += num4 - num6.X; num7.X = (float)Math.Ceiling((double)num7.X); LinearGradientBrush brush2 = new LinearGradientBrush { ColorInterpolationMode = ColorInterpolationMode.SRgbLinearInterpolation, SpreadMethod = GradientSpreadMethod.Pad }; brush2.GradientStops.Add(new GradientStop(Color.White, 0.0)); brush2.GradientStops.Add(new GradientStop(Color.White, ((double)(e.Bounds.Width - UIUtil.ScaleWidth(0x18))) / ((double)e.Bounds.Width))); brush2.GradientStops.Add(new GradientStop(Color.Transparent, 1.0)); brush2.EndPoint = new PointDouble((double)e.Bounds.Width, 0.0); brush = brush2; } using (context.CreateLayer(null)) { context.PushLayer(layer, new RectDouble?(num7), null, AntialiasMode.Aliased, new Matrix3x2Double?(Matrix3x2Float.Identity), 1.0, brush, LayerOptions.None); context.DrawBitmap(bitmap.DeviceBitmap, new RectDouble?(num7), 1.0, BitmapInterpolationMode.Linear, null); context.PopLayer(); } } } }
/// <summary> /// Creates a new instance. /// </summary> /// <param name="ui">Implementation of the platform dependent UI module.</param> internal PropView(IUserInterface ui) : base(ui) { _Layout = new PropTextLayout(this); }
/// <summary> /// Rectで指定された範囲にドキュメントを描く /// </summary> /// <param name="updateRect">描写する範囲</param> /// <param name="force">キャッシュした内容を使用しない場合は真を指定する</param> /// <remarks>描写する範囲がPageBoundより小さい場合、キャッシュされた内容を使用することがあります。なお、レタリング後にrender.CacheContent()を呼び出さなかった場合は更新範囲にかかわらずキャッシュを使用しません</remarks> public override void Draw(Rectangle updateRect, bool force = false) { if (this.LayoutLines.Count == 0) { return; } IEditorRender render = (IEditorRender)base.render; if (render == null) { return; } if ((updateRect.Height < this.PageBound.Height || updateRect.Width < this.PageBound.Width) && render.IsVaildCache() && !force) { render.DrawCachedBitmap(updateRect, updateRect); } else { Rectangle background = this.PageBound; render.FillBackground(background); if (this.Document.HideRuler == false) { this.DrawRuler(); } double endposy = this.render.TextArea.Bottom; Point pos = this.render.TextArea.TopLeft; pos.X -= this.Src.X; //画面上では行をずらして表示する pos.Y += this.Src.OffsetY; this.render.BeginClipRect(this.render.TextArea); for (int i = this.Src.Row; i < this.LayoutLines.Count; i++) { int lineIndex = this.LayoutLines.GetIndexFromLineNumber(i); int lineLength = this.LayoutLines.GetLengthFromLineNumber(i); ITextLayout layout = this.LayoutLines.GetLayout(i); if (pos.Y > endposy) { break; } FoldingItem foldingData = this.LayoutLines.FoldingCollection.Get(lineIndex, lineLength); if (foldingData != null) { if (this.LayoutLines.FoldingCollection.IsHidden(lineIndex)) { continue; } } this.render.DrawOneLine(this.Document, this.LayoutLines, i, pos.X, pos.Y); pos.Y += layout.Height; } this.render.EndClipRect(); //リセットしないと行が正しく描けない pos = this.render.TextArea.TopLeft; //画面上では行をずらして表示する pos.Y += this.Src.OffsetY; Size lineNumberSize = new Size(this.render.LineNemberWidth, this.render.TextArea.Height); for (int i = this.Src.Row; i < this.LayoutLines.Count; i++) { int lineIndex = this.LayoutLines.GetIndexFromLineNumber(i); int lineLength = this.LayoutLines.GetLengthFromLineNumber(i); ITextLayout layout = this.LayoutLines.GetLayout(i); if (pos.Y > endposy) { break; } FoldingItem foldingData = this.LayoutLines.FoldingCollection.Get(lineIndex, lineLength); if (foldingData != null) { if (this.LayoutLines.FoldingCollection.IsHidden(lineIndex)) { continue; } if (foldingData.IsFirstLine(this.LayoutLines, i) && foldingData.End >= lineIndex + lineLength) { render.DrawFoldingMark(foldingData.Expand, this.PageBound.X + this.GetRealtiveX(AreaType.FoldingArea), pos.Y); } } if (this.Document.DrawLineNumber) { this.render.DrawString((i + 1).ToString(), this.PageBound.X + this.GetRealtiveX(AreaType.LineNumberArea), pos.Y, StringAlignment.Right, lineNumberSize, StringColorType.LineNumber); } DrawUpdateArea(i, pos.Y); if (i == this.Document.CaretPostion.row) { this.DrawLineMarker(pos, layout); } pos.Y += layout.Height; } this.Document.SelectGrippers.BottomLeft.Draw(this.render); this.Document.SelectGrippers.BottomRight.Draw(this.render); render.CacheContent(); } this.DrawInsertPoint(); this.DrawCaret(); }
public override bool Compose(DrawContext dc, Style c, int availWidth, out ItemMetrics im, bool suppressWhitespace, out ITextLayout next) { TextItemMetrics metrics=new TextItemMetrics(this); im=metrics; this.style=c; next=null; // TODO: L: optimise Size sz=dc.Graphics.MeasureText(" "); spaceWidth=sz.Width; height=sz.Height; width=0; // get the font ascent ascent=c.FontAscent; if ( textNode.NodeType == XmlNodeType.SignificantWhitespace ) { // special case, simply set to single space width and return width=sz.Width; len=textNode.Value.Length; metrics.CanBreakBefore=true; metrics.CanBreakAfter=true; return true; } int startSpaceCount=GetStartSpaceCount(); if ( startSpaceCount > 0 && suppressWhitespace ) { TrimStart(startSpaceCount); startSpaceCount=0; } if ( startSpaceCount > 1 ) { TrimStart(startSpaceCount - 1); startSpaceCount=1; } len=startSpaceCount; if ( start+len == textNode.Value.Length ) { // this is pure whitespace width=sz.Width; return true; } metrics.CanBreakBefore=startSpaceCount > 0; bool hasMoreContent=true; bool firstWord=true; bool fit=false; int endSpaceCount=0; int finalWidth=startSpaceCount * spaceWidth; int splitLen=0; int splitWidth=0; bool needNewline=false; // bool newline=false; while ( hasMoreContent ) { int testLen; int tesc; hasMoreContent=IncludeNextWord(out testLen, out tesc); string segString=textNode.Value.Substring(start+len, testLen-len-tesc); string testString=ProcessText(segString); int segWidth=dc.Graphics.MeasureText(testString).Width; int testWidth=finalWidth+segWidth; // string testString=ProcessText(textNode.Value.Substring(start, testLen-tesc)); // int testWidth=dc.Graphics.MeasureText(testString).Width; fit=testWidth < availWidth; if ( fit || firstWord ) { // either it fits or it has to fit because this is the first word metrics.AddSegment(start+len, testLen-len, segWidth); splitLen=len; len=testLen; splitWidth=finalWidth; endSpaceCount=tesc; finalWidth=testWidth + (endSpaceCount > 0 ? spaceWidth : 0); if ( !fit && firstWord ) needNewline=true; if ( !fit || endSpaceCount > 1 ) break; } else break; firstWord=false; } // this is handled by custom class // if ( style.Pre && newline ) // bi.ForceBreakAfter=true; Debug.Assert(len > 0, "Must have laid out something!"); // at this point we have these possibilities: // everything fit - fit == true, nothing to do, return true // not everything fit - fit == false, get next, return false // and cannot split - oldLen=-1, return false // and can split - oldLen > 0, ConfigureSplitInfo, return true metrics.CanBreakAfter=endSpaceCount > 0; width=finalWidth; if ( splitLen > 0 ) { canSplit=true; splitIndex=splitLen; splitLeftWidth=splitWidth; splitRightWidth=finalWidth-splitWidth; } if ( start+len < textNode.Value.Length ) next=GetNextFragment(); if ( endSpaceCount > 1 ) { TrimEnd(endSpaceCount - 1); endSpaceCount=1; } return !needNewline; }
/// <summary> /// srcRowを起点としてrect_heightが収まる行とオフセットYを求めます /// </summary> /// <param name="srcRow">起点となる行</param> /// <param name="rect_hight">Y方向のバウンディングボックス</param> /// <returns>失敗した場合、NULL。成功した場合、行とオフセットY</returns> public SrcPoint GetNearstRowAndOffsetY(int srcRow, double rect_hight) { int i; if (rect_hight > 0) { for (i = srcRow; i < this.Document.LayoutLines.Count; i++) { ITextLayout layout = this.Document.LayoutLines.GetLayout(i); int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(i); int lineLength = this.LayoutLines.GetLengthFromLineNumber(i); double layoutHeight = layout.Height; if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex)) { continue; } if (rect_hight == 0) { return(new SrcPoint(0, i, 0)); } if (rect_hight - layoutHeight < 0) { return(new SrcPoint(0, i, rect_hight)); } rect_hight -= layoutHeight; } if (rect_hight >= 0) { return(new SrcPoint(0, srcRow, 0)); } } else if (rect_hight < 0) { for (i = srcRow - 1; i >= 0; i--) { ITextLayout layout = this.Document.LayoutLines.GetLayout(i); int lineHeadIndex = this.LayoutLines.GetIndexFromLineNumber(i); int lineLength = this.LayoutLines.GetLengthFromLineNumber(i); double layoutHeight = layout.Height; if (this.LayoutLines.FoldingCollection.IsHidden(lineHeadIndex)) { continue; } if (rect_hight == 0) { return(new SrcPoint(0, i, 0)); } if (rect_hight + layoutHeight >= 0) { return(new SrcPoint(0, i, layoutHeight + rect_hight)); } rect_hight += layoutHeight; } return(new SrcPoint(0, 0, 0)); } return(new SrcPoint(0, srcRow, 0)); }
/// <summary> /// Creates a new instance. /// </summary> internal PropWrapView(View other) : base(other) { _Layout = new PropWrapTextLayout(this); Document.ViewParam.ScrollPosX = 0; }
public override bool Compose(DrawContext dc, Style c, int width, out ItemMetrics bi, bool suppressWhitespace, out ITextLayout next) { this.style=c; bi=new ItemMetrics(this); next=null; // idea here is just to scan for next line break // TODO: M: may need to deal with double spaces, tabs, etc string text=Text; int ptr=text.IndexOf('\n'); int measureLen=len; if ( ptr >= 0 ) { bi.ForceBreakAfter=true; len=ptr+1; measureLen=len-1; if ( len < text.Length ) next=GetNextFragment(); } if ( measureLen > 0 && Text[measureLen-1]=='\r' ) measureLen--; Size sz=dc.Graphics.MeasureText(Text.Substring(0, measureLen)); height=dc.Graphics.GetFontHeight(); this.width=sz.Width; ascent=c.FontAscent; return true; }
public void DrawTextLayout(PointFloat origin, ITextLayout textLayout, IBrush defaultForegroundBrush, DrawTextOptions options) { base.innerRefT.DrawTextLayout(origin, textLayout, defaultForegroundBrush, options); }
public abstract bool Compose(DrawContext dc, Style c, int width, out ItemMetrics bi, bool suppressWhitespace, out ITextLayout next);
public static ITextLayout CreateRef(this ITextLayout objectRef) => ((ITextLayout)objectRef.CreateRef(typeof(ITextLayout)));