public PaintRecord(TextStyle style, SkTextBlob text, SKFontMetrics metrics, int line, double run_width) { this.style_ = style; this.text_ = text; this.metrics_ = metrics; //C++ TO C# CONVERTER TODO TASK: The following line was determined to be a copy assignment (rather than a reference assignment) - this should be verified and a 'CopyFrom' method should be created: //ORIGINAL LINE: this.line_ = line; this.line_ = line; this.run_width_ = run_width; }
private void InitializeRendering() { paint.Color = SKColors.Black; paint.TextSize = FontSize; paint.Typeface = this.Typeface; paint.SubpixelText = true; paint.LcdRenderText = true; paint.IsAntialias = true; typeMetrics = paint.FontMetrics; TextViewModel.VisualBuffer.Changed += VisualBuffer_Changed; }
private SKPaint getTextBlock(double fontSize) { if (!this.textBlocks.ContainsKey(fontSize)) { SKPaint textBlock = new SKPaint(); Label label = new Label(); textBlock.TextSize = (float)fontSize; textBlock.Typeface = SKTypeface.FromFamilyName(label.FontFamily); // leave enough height for the characters for the highest ("M") and lowest ("g") characters SKFontMetrics metrics = new SKFontMetrics(); textBlock.GetFontMetrics(out metrics); this.fontLineHeight = metrics.Descent - metrics.Ascent; SKRect bounds = new SKRect(); textBlock.MeasureText("M", ref bounds); this.leftMargin = bounds.Left; this.textBlocks[fontSize] = textBlock; } return(this.textBlocks[fontSize]); }
/// <summary> /// Generates a bitmap using the provided textData and font info. Note that /// you are responsible for calling <code>Dispose</code> on the returned bitmap. /// </summary> /// <param name="textData">The <code>ITextData</code> to read from</param> /// <returns>The generated <code>SKBitmap</code></returns> public SKBitmap GenerateBitmap(ITextData textData) { using (var paint = new SKPaint()) { paint.IsAntialias = this.ShouldAntialias; paint.IsDither = this.ShouldDither; paint.IsAutohinted = this.ShouldHint; var font = this.Font; paint.Typeface = font.Typeface.SkiaTypeface; paint.TextSize = font.TextSize; paint.TextEncoding = SKTextEncoding.Utf8; paint.SubpixelText = true; paint.DeviceKerningEnabled = false; paint.Color = font.Color.SkiaColor; var backgroundColor = this.BackgroundColor; int textWidth = textData.Width; int textHeight = textData.Height; // spacing reserved for a single character SKFontMetrics fontMetrics = paint.FontMetrics; int characterSpacing = font.CharacterSpacing; Debug.Assert(characterSpacing > 0); // bitmap may not be big enough for all text if using // non-monospace characters and/or characterSize/ is not // sufficient. Too bad. int bitmapWidth = characterSpacing * textWidth; int bitmapHeight = characterSpacing * textHeight; Debug.Assert(bitmapWidth > 0); Debug.Assert(bitmapHeight > 0); // NOTE: this will need to be disposed by the caller. var bitmap = new SKBitmap( bitmapWidth, bitmapHeight, SKImageInfo.PlatformColorType, SKAlphaType.Premul ); using (var canvas = new SKCanvas(bitmap)) { bitmap.Erase(backgroundColor); var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = 1 }; Parallel.For(0, textHeight, parallelOptions, y => { Parallel.For(0, textWidth, x => { string charAsString = textData[x, y].ToString(); // dimensions of actual printed chars float charWidth = paint.MeasureText(charAsString); float charHeight = -fontMetrics.Ascent; Debug.Assert(charWidth > 0); Debug.Assert(charHeight > 0); // the actual position to render them. // they should be centered in the space allocated to them. float textX = (x * characterSpacing) + (characterSpacing - charWidth) * 0.5f; float textY = (y * characterSpacing) + (characterSpacing * 0.75f); canvas.DrawText( text: textData[x, y].ToString(), x: textX, y: textY, paint: paint ); }); }); } return(bitmap); } }
public override RSize MeasureString(string str, RFont font) { var f = ((FontAdapter)font).Font; var textSize = SkRenderer.GetTextBound(str, f); var size = new Size((int)textSize.Width, (int)textSize.Height); var p = SkRenderer.PaintFromFont(f); // if (!GloablRenderSettings.UseGdiMeasureFont) // { // // p.Typeface = SKTypeface.FromFamilyName(f.OriginalFontName); // p.TextSize = f.Size; // p.TextAlign = SKTextAlign.Left; // // var r = new SKRect(); // var d = p.MeasureText(str, ref r); // float whiteSpaceWidth = d - r.Width; // r.Left -= whiteSpaceWidth / 2; // r.Right += whiteSpaceWidth / 2; // r.Top -= whiteSpaceWidth * 2; // r.Bottom += whiteSpaceWidth * 2; // size = new Size((int) r.Width + (int) (r.Width / 2), (int) f.Height); // var winSize = new Size(); // SkRendererAdapter.GetTextExtentPoint32(_hdc, str, str.Length, ref winSize); // Console.WriteLine("123"); // } // else // { // SkRendererAdapter.GetTextExtentPoint32(_hdc, str, str.Length, ref size); // } if (font.Height < 0) { // if (!GloablRenderSettings.UseGdiMeasureFont) // { var metrics = new SKFontMetrics(); var m = p.GetFontMetrics(out metrics); var underlineOffset = (int) (metrics.XHeight - metrics.Descent + (metrics.UnderlinePosition ?? 0) + 1); ((FontAdapter)font).SetMetrics(size.Height, underlineOffset); Console.WriteLine(); // } // else // { // TextMetric lptm; // SkRendererAdapter.GetTextMetrics(_hdc, out lptm); // var underlineOffset = lptm.tmHeight - lptm.tmDescent + lptm.tmUnderlined + 1; // ((FontAdapter) font).SetMetrics(size.Height, underlineOffset); // } } return(Utils.Convert(size)); }
public static float GetHeight(this SKFontMetrics me) => me.Descent - me.Ascent;
internal unsafe void Run() { if (!needRun) { return; } lines.Clear(); //设置paint参数 var paint = new SKPaint(); paint.TextEncoding = SKTextEncoding.Utf16; font.ApplyToSKPaint(paint, GraphicsUnit.Pixel, dpi); //注意目标类型为像素 //测量FontMetric SKFontMetrics metrics = font.FontMetrics; //根据文字排版方向确认限宽及限高 float maxWidth = Math.Min(32767, IsVertical ? height : width); //TODO: float maxHeight = IsVertical ? width : height; //TODO:计算高度不满足一行的情况 fixed(char *ptr = Text) { byte *textPtr = (byte *)ptr; byte *startTextPtr = (byte *)ptr; int totalBytes = text.Length * 2; int leftBytes = totalBytes; float y = 0; while (true) { //根据是否允许换行,调用不同的breakText方法 var measuredWidth = 0f; var lineBytes = (int)paint.BreakText(new IntPtr(startTextPtr), new IntPtr(leftBytes), maxWidth, out measuredWidth); //var lineBytes = SkiaApi.sk_paint_break_text_icu(paint, new IntPtr(startTextPtr), leftBytes, maxWidth, null); //TODO:***** fix maxWidth var newLine = new TextLayoutLine(this); newLine.startByteIndex = (int)(startTextPtr - textPtr); newLine.byteLength = lineBytes; newLine.widths = paint.GetGlyphWidths(new IntPtr(startTextPtr), lineBytes); //newLine.startCharIndex = 0; //TODO: //根据对齐方式计算Line的offsetX值 if (stringFormat != null && stringFormat.Alignment != StringAlignment.Near) { //计算当前行Ink总宽度 float lineInkWidth = 0f; for (int i = 0; i < newLine.widths.Length; i++) { lineInkWidth += newLine.widths[i]; } float lineSpace = width - lineInkWidth; if (lineSpace > 0f) { if (stringFormat.Alignment == StringAlignment.Center) { newLine.offsetX = lineSpace / 2f; } else if (stringFormat.Alignment == StringAlignment.Far) { newLine.offsetX = lineSpace; } } } //添加新行 lines.Add(newLine); //判断是否允许换行,不允许直接退出循环 if (IsNoWrap) { break; } //计算下一行高度是否超出限高 y = y - metrics.Ascent + metrics.Descent + metrics.Leading; if ((y - metrics.Ascent + metrics.Descent) > maxHeight) { break; } //偏移剩余部分,并判断是否全部计算完毕 startTextPtr += lineBytes; if ((int)(startTextPtr - textPtr) >= totalBytes) { break; } leftBytes -= lineBytes; } } //根据对齐方式计算offsetY的值 CalcOffsetY(); needRun = false; }