Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

System.Drawing.Common and RTL support #25573

Closed
VahidN opened this issue Mar 22, 2018 · 6 comments
Closed

System.Drawing.Common and RTL support #25573

VahidN opened this issue Mar 22, 2018 · 6 comments

Comments

@VahidN
Copy link

VahidN commented Mar 22, 2018

Currently System.Drawing.Common version "4.5.0-preview1-26216-02" doesn't support RTL on operating systems other than Windows. Here is a sample to demonstrate this issue:

SystemDrawingCommonRtlTest.csproj file

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="System.Drawing.Common" Version="4.5.0-preview1-26216-02" />
  </ItemGroup>
</Project>

Program.cs file

using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.Runtime.InteropServices;

namespace SystemDrawingCommonRtlTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var text = "آزمايش"; // = Test
            var tahomaFont = new Font("Tahoma", 40, FontStyle.Regular, GraphicsUnit.Pixel);

            var (height, width) = getImageSize(text, tahomaFont);

            using (var pic = new Bitmap(width, height))
            {
                using (var graphics = Graphics.FromImage(pic))
                {
                    graphics.SmoothingMode = SmoothingMode.AntiAlias;
                    graphics.SmoothingMode = SmoothingMode.HighQuality;
                    graphics.CompositingQuality = CompositingQuality.HighQuality;
                    graphics.InterpolationMode = InterpolationMode.High;
                    graphics.TextRenderingHint = TextRenderingHint.AntiAlias;

                    using (var font = tahomaFont)
                    {
                        using (var format = new StringFormat())
                        {
                            format.FormatFlags = StringFormatFlags.DirectionRightToLeft;
                            graphics.DrawString(
                                text,
                                font,
                                new SolidBrush(Color.Black),
                                new Rectangle(0, 0, width, height),
                                format);

                            pic.Save($"rtl-text-{RuntimeInformation.OSDescription}.png", ImageFormat.Png);
                        }
                    }
                }
            }
        }

        private static (int Height, int Width) getImageSize(string text, Font font)
        {
            SizeF size;
            using (var bmp = new Bitmap(1, 1))
            {
                using (var g = Graphics.FromImage(bmp))
                {
                    size = g.MeasureString(text, font);
                }
            }

            const int margin = 8;
            return ((int)size.Height + margin, (int)size.Width + margin);
        }
    }
}

And here are its output
On Windows 10: It works correctly
rtl-text-microsoft windows 10 0 16299

On Linux (Ubuntu): Characters are separated and rotated
rtl-text-linux 4 4 0-31-generic 50-ubuntu smp wed jul 13 00 07 12 utc 2016

@filipnavara
Copy link
Member

It may work if libgdiplus on the system is built with Pango support. That's usually not the default though.

@safern
Copy link
Member

safern commented Mar 23, 2018

@filipnavara can we fix this in libgdiplus to make it work by default?

Marking as future as this is libgdiplus behavior.

@filipnavara
Copy link
Member

@safern I think that's a question for Linux distro maintainers. There are two text rendering backends in libgdiplus. The default one is using Cairo (https://cairographics.org/manual/cairo-text.html), which explicitly calls the text API unsatisfactory for any serious use:

The functions with text in their name form cairo's toy text API. The toy API takes UTF-8 encoded text and is limited in its functionality to rendering simple left-to-right text with no advanced features. That means for example that most complex scripts like Hebrew, Arabic, and Indic scripts are out of question. No kerning or correct positioning of diacritical marks either. The font selection is pretty limited too and doesn't handle the case that the selected font does not cover the characters in the text. This set of functions are really that, a toy text API, for testing and demonstration purposes. Any serious application should avoid them.

The functions with glyphs in their name form cairo's low-level text API. The low-level API relies on the user to convert text to a set of glyph indexes and positions. This is a very hard problem and is best handled by external libraries, like the pangocairo that is part of the Pango text layout and rendering library. Pango is available from http://www.pango.org/.

The other one uses the Pango library for text layout and supports some more advanced scenarios. It's a matter of pushing the distributions to include this additional dependency and configuring the library with --with-pango option.

@filipnavara
Copy link
Member

On a second thought I think most of the Linux distributions already have Pango installed, so maybe it should just be used when available without an extra configuration option. I am no expert on autoconf/automake to make that possible. Additionally, the Pango backend needs some serious testing.

@filipnavara
Copy link
Member

I have updated the Pango code in libgdiplus and submitted PRs for problems that I could find. It is still nowhere near as tested as the equivalent Cairo text rendering, so any help with that will be greatly appreciated.

@safern
Copy link
Member

safern commented Mar 28, 2018

@filipnavara thanks for explaining and taking a look, it is really helpful to have active contributors fixing libgdiplus issues that we hit in our System.Drawing implementation :)

I guess then this issue can be closed since it is an issue in libgdiplus and dependent to an external dependency we can't really do much from corefx side.

@safern safern closed this as completed Mar 28, 2018
@msftgits msftgits transferred this issue from dotnet/corefx Jan 31, 2020
@msftgits msftgits added this to the 2.1.0 milestone Jan 31, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 17, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants