/// <summary> /// Measure the width of string under max width restriction calculating the number of characters that can fit and the width those characters take.<br/> /// Not relevant for platforms that don't render HTML on UI element. /// </summary> /// <param name="str">the string to measure</param> /// <param name="font">the font to measure string with</param> /// <param name="maxWidth">the max width to calculate fit characters</param> /// <param name="charFit">the number of characters that will fit under <see cref="maxWidth"/> restriction</param> /// <param name="charFitWidth">the width that only the characters that fit into max width take</param> public abstract void MeasureString(string str, RFont font, double maxWidth, out int charFit, out double charFitWidth);
/// <summary> /// Draw the given string using the given font and foreground color at given location. /// </summary> /// <param name="str">the string to draw</param> /// <param name="font">the font to use to draw the string</param> /// <param name="color">the text color to set</param> /// <param name="point">the location to start string draw (top-left)</param> /// <param name="size">used to know the size of the rendered text for transparent text support</param> /// <param name="rtl">is to render the string right-to-left (true - RTL, false - LTR)</param> public abstract void DrawString(String str, RFont font, RColor color, RPoint point, RSize size, bool rtl);
public override void MeasureString(string str, RFont font, double maxWidth, out int charFit, out double charFitWidth) { charFit = 0; charFitWidth = 0; if (_useGdiPlusTextRendering) { ReleaseHdc(); var size = MeasureString(str, font); for (int i = 1; i <= str.Length; i++) { charFit = i - 1; RSize pSize = MeasureString(str.Substring(0, i), font); if (pSize.Height <= size.Height && pSize.Width < maxWidth) charFitWidth = pSize.Width; else break; } } else { #if !MONO SetFont(font); var size = new Size(); Win32Utils.GetTextExtentExPoint(_hdc, str, str.Length, (int)Math.Round(maxWidth), _charFit, _charFitWidth, ref size); charFit = _charFit[0]; charFitWidth = charFit > 0 ? _charFitWidth[charFit - 1] : 0; #endif } }
/// <summary> /// Measure the width and height of string <paramref name="str"/> when drawn on device context HDC /// using the given font <paramref name="font"/>. /// </summary> /// <param name="str">the string to measure</param> /// <param name="font">the font to measure string with</param> /// <returns>the size of the string</returns> public abstract RSize MeasureString(string str, RFont font);
public override RSize MeasureString(string str, RFont font) { var text = GetText(str, font); var measure = text.Measure(); return new RSize(measure.Width, measure.Height); }
public override void MeasureString(string str, RFont font, double maxWidth, out int charFit, out double charFitWidth) { var text = GetText(str, font); var fullLength = text.Measure().Width; if (fullLength < maxWidth) { charFitWidth = fullLength; charFit = str.Length; return; } int lastLen = 0; double lastMeasure = 0; BinarySearch(len => { text = GetText(str.Substring(0, len), font); var size = text.Measure().Width; lastMeasure = size; lastLen = len; if (size <= maxWidth) return -1; return 1; }, 0, str.Length); if (lastMeasure > maxWidth) { lastLen--; lastMeasure = GetText(str.Substring(0, lastLen), font).Measure().Width; } charFit = lastLen; charFitWidth = lastMeasure; }
public override void DrawString(string str, RFont font, RColor color, RPoint point, RSize size, bool rtl) { var colorConv = ((BrushAdapter)_adapter.GetSolidBrush(color)).Brush; bool glyphRendered = false; GlyphTypeface glyphTypeface = ((FontAdapter)font).GlyphTypeface; if (glyphTypeface != null) { double width = 0; ushort[] glyphs = new ushort[str.Length]; double[] widths = new double[str.Length]; int i = 0; for (; i < str.Length; i++) { ushort glyph; if (!glyphTypeface.CharacterToGlyphMap.TryGetValue(str[i], out glyph)) break; glyphs[i] = glyph; width += glyphTypeface.AdvanceWidths[glyph]; widths[i] = 96d / 72d * font.Size * glyphTypeface.AdvanceWidths[glyph]; } if (i >= str.Length) { point.Y += glyphTypeface.Baseline * font.Size * 96d / 72d; point.X += rtl ? 96d / 72d * font.Size * width : 0; glyphRendered = true; var glyphRun = new GlyphRun(glyphTypeface, rtl ? 1 : 0, false, 96d / 72d * font.Size, glyphs, Utils.ConvertRound(point), widths, null, null, null, null, null, null); _g.DrawGlyphRun(colorConv, glyphRun); } } if (!glyphRendered) { var formattedText = new FormattedText(str, CultureInfo.CurrentCulture, rtl ? FlowDirection.RightToLeft : FlowDirection.LeftToRight, ((FontAdapter)font).Font, 96d / 72d * font.Size, colorConv); point.X += rtl ? formattedText.Width : 0; _g.DrawText(formattedText, Utils.ConvertRound(point)); } }
public override RSize MeasureString(string str, RFont font) { double width = 0; GlyphTypeface glyphTypeface = ((FontAdapter)font).GlyphTypeface; if (glyphTypeface != null) { for (int i = 0; i < str.Length; i++) { if (glyphTypeface.CharacterToGlyphMap.ContainsKey(str[i])) { ushort glyph = glyphTypeface.CharacterToGlyphMap[str[i]]; double advanceWidth = glyphTypeface.AdvanceWidths[glyph]; width += advanceWidth; } else { width = 0; break; } } } if (width <= 0) { var formattedText = new FormattedText(str, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, ((FontAdapter)font).Font, 96d / 72d * font.Size, Brushes.Red); return new RSize(formattedText.WidthIncludingTrailingWhitespace, formattedText.Height); } return new RSize(width * font.Size * 96d / 72d, font.Height); }
public override void MeasureString(string str, RFont font, double maxWidth, out int charFit, out double charFitWidth) { charFit = 0; charFitWidth = 0; bool handled = false; GlyphTypeface glyphTypeface = ((FontAdapter)font).GlyphTypeface; if (glyphTypeface != null) { handled = true; double width = 0; for (int i = 0; i < str.Length; i++) { if (glyphTypeface.CharacterToGlyphMap.ContainsKey(str[i])) { ushort glyph = glyphTypeface.CharacterToGlyphMap[str[i]]; double advanceWidth = glyphTypeface.AdvanceWidths[glyph] * font.Size * 96d / 72d; if (!(width + advanceWidth < maxWidth)) { charFit = i; charFitWidth = width; break; } width += advanceWidth; } else { handled = false; break; } } } if (!handled) { var formattedText = new FormattedText(str, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, ((FontAdapter)font).Font, 96d / 72d * font.Size, Brushes.Red); charFit = str.Length; charFitWidth = formattedText.WidthIncludingTrailingWhitespace; } }
/// <summary> /// Special draw logic to draw transparent text using GDI.<br/> /// 1. Create in-memory DC<br/> /// 2. Copy background to in-memory DC<br/> /// 3. Draw the text to in-memory DC<br/> /// 4. Copy the in-memory DC to the proper location with alpha blend<br/> /// </summary> private static void DrawTransparentText(IntPtr hdc, string str, RFont font, Point point, Size size, Color color) { IntPtr dib; var memoryHdc = Win32Utils.CreateMemoryHdc(hdc, size.Width, size.Height, out dib); try { // copy target background to memory HDC so when copied back it will have the proper background Win32Utils.BitBlt(memoryHdc, 0, 0, size.Width, size.Height, hdc, point.X, point.Y, Win32Utils.BitBltCopy); // Create and select font Win32Utils.SelectObject(memoryHdc, ((FontAdapter)font).HFont); Win32Utils.SetTextColor(memoryHdc, (color.B & 0xFF) << 16 | (color.G & 0xFF) << 8 | color.R); // Draw text to memory HDC Win32Utils.TextOut(memoryHdc, 0, 0, str, str.Length); // copy from memory HDC to normal HDC with alpha blend so achieve the transparent text Win32Utils.AlphaBlend(hdc, point.X, point.Y, size.Width, size.Height, memoryHdc, 0, 0, size.Width, size.Height, new BlendFunction(color.A)); } finally { Win32Utils.ReleaseMemoryHdc(memoryHdc, dib); } }
/// <summary> /// Set a resource (e.g. a font) for the specified device context. /// WARNING: Calling Font.ToHfont() many times without releasing the font handle crashes the app. /// </summary> private void SetFont(RFont font) { InitHdc(); Win32Utils.SelectObject(_hdc, ((FontAdapter)font).HFont); }
public override void DrawString(string str, RFont font, RColor color, RPoint point, RSize size, bool rtl) { if (_useGdiPlusTextRendering) { ReleaseHdc(); SetRtlAlignGdiPlus(rtl); var brush = ((BrushAdapter)_adapter.GetSolidBrush(color)).Brush; _g.DrawString(str, ((FontAdapter)font).Font, brush, (int)(Math.Round(point.X) + (rtl ? size.Width : 0)), (int)Math.Round(point.Y), _stringFormat2); } else { #if !MONO var pointConv = Utils.ConvertRound(point); var colorConv = Utils.Convert(color); if (color.A == 255) { SetFont(font); SetTextColor(colorConv); SetRtlAlignGdi(rtl); Win32Utils.TextOut(_hdc, pointConv.X, pointConv.Y, str, str.Length); } else { InitHdc(); SetRtlAlignGdi(rtl); DrawTransparentText(_hdc, str, font, pointConv, Utils.ConvertRound(size), colorConv); } #endif } }
public override void MeasureString(string str, RFont font, double maxWidth, out int charFit, out double charFitWidth) { using (var g = new GraphicsAdapter()) { g.MeasureString(str, font, maxWidth, out charFit, out charFitWidth); } }
public override void MeasureString(string str, RFont font, double maxWidth, out int charFit, out double charFitWidth) { using (var g = new GraphicsAdapter(_control.CreateGraphics(), _useGdiPlusTextRendering, true)) { g.MeasureString(str, font, maxWidth, out charFit, out charFitWidth); } }
public override void DrawString(string str, RFont font, RColor color, RPoint point, RSize size, bool rtl) { var xBrush = ((BrushAdapter)_adapter.GetSolidBrush(color)).Brush; _g.DrawString(str, ((FontAdapter)font).Font, (XBrush)xBrush, point.X, point.Y, _stringFormat); }
public override RSize MeasureString(string str, RFont font) { var fontAdapter = (FontAdapter)font; var realFont = fontAdapter.Font; var size = _g.MeasureString(str, realFont, _stringFormat); if (font.Height < 0) { var height = realFont.Height; var descent = realFont.Size * realFont.FontFamily.GetCellDescent(realFont.Style) / realFont.FontFamily.GetEmHeight(realFont.Style); fontAdapter.SetMetrics(height, (int)Math.Round((height - descent + 1f))); } return Utils.Convert(size); }
FormattedText GetText(string str, RFont font) { var f = ((FontAdapter)font); return new FormattedText(str, f.Name, font.Size, f.FontStyle, TextAlignment.Left, f.Weight); }
public override void MeasureString(string str, RFont font, double maxWidth, out int charFit, out double charFitWidth) { // there is no need for it - used for text selection throw new NotSupportedException(); }
public override void DrawString(string str, RFont font, RColor color, RPoint point, RSize size, bool rtl) { var text = GetText(str, font); text.Constraint = Util.Convert(size); _g.DrawText(new SolidColorBrush(Util.Convert(color)), Util.Convert(point), text); }
public override RSize MeasureString(string str, RFont font) { if (_useGdiPlusTextRendering) { ReleaseHdc(); var fontAdapter = (FontAdapter)font; var realFont = fontAdapter.Font; _characterRanges[0] = new CharacterRange(0, str.Length); _stringFormat.SetMeasurableCharacterRanges(_characterRanges); var size = _g.MeasureCharacterRanges(str, realFont, RectangleF.Empty, _stringFormat)[0].GetBounds(_g).Size; if (font.Height < 0) { var height = realFont.Height; var descent = realFont.Size * realFont.FontFamily.GetCellDescent(realFont.Style) / realFont.FontFamily.GetEmHeight(realFont.Style); #if !MONO fontAdapter.SetMetrics(height, (int)Math.Round((height - descent + .5f))); #else fontAdapter.SetMetrics(height, (int)Math.Round((height - descent + 1f))); #endif } return Utils.Convert(size); } else { #if !MONO SetFont(font); var size = new Size(); Win32Utils.GetTextExtentPoint32(_hdc, str, str.Length, ref size); if (font.Height < 0) { TextMetric lptm; Win32Utils.GetTextMetrics(_hdc, out lptm); ((FontAdapter)font).SetMetrics(size.Height, lptm.tmHeight - lptm.tmDescent + lptm.tmUnderlined + 1); } return Utils.Convert(size); #else throw new InvalidProgramException("Invalid Mono code"); #endif } }