diff --git a/README.md b/README.md index 02c1554bd..f94a83b54 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,8 @@ For custom configurations, see [CONFIG.md](CONFIG.md). For testing and profiling, see [TESTING.md](TESTING.md). +For cross-compiling to Windows from Linux or macOS, see [README.mingw.md](README.mingw.md). + To get a better idea of where HarfBuzz stands in the text rendering stack you may want to read [State of Text Rendering 2024][6]. Here are a few presentation slides about HarfBuzz at the diff --git a/README.mingw.md b/README.mingw.md index 60629f6fc..e04205e91 100644 --- a/README.mingw.md +++ b/README.mingw.md @@ -1,58 +1,180 @@ -For the development of HarfBuzz, the Microsoft shaping technology, Uniscribe, -as a widely used and tested shaper is used as more-or-less OpenType reference -implementation and that specially is important where OpenType specification -is or wasn't that clear. For having access to Uniscribe on Linux/macOS these -steps are recommended: +Most HarfBuzz developers do so on Linux or macOS. However, HarfBuzz is a +cross-platform library and it is important to ensure that it works on Windows +as well. In particular, we use this workflow to develop and test the HarfBuzz +Uniscribe shaper and DirectWrite shaper and font backend, all from Linux or +macOS. -You want to follow the 32bit instructions. The 64bit equivalents are included -for reference. +This document provides instructions for cross-compiling HarfBuzz on Linux or +macOS, for Windows, using the MinGW toolchain, and running tests and utilties +under Wine. + +We then discuss using native Windows Uniscribe or DirectWrite DLLs, which +allows you to test HarfBuzz's shaping against the Microsoft shaping engines +instead of those provided by Wine. + +This document assumes that you are familiar with building HarfBuzz on Linux or +macOS. + +You can build for 32bit or 64bit Windows. If your intention is to use a native +Uniscribe usp10.dll from Windows 7 or before, you would need to build for 32bit. +If you want to use a native DirectWrite DLL from Windows 10 or later, you would +need to build for 64bit. 1. Install Wine. - - Fedora: `dnf install wine`. -2. Install `mingw-w64` compiler. - - Fedora, 32bit: `dnf install mingw32-gcc-c++` - - Fedora, 64bit: `dnf install mingw64-gcc-c++` - - Debian: `apt install g++-mingw-w64` - - Mac: `brew install mingw-w64` + - Fedora: `dnf install wine`. + - Mac: `brew install wine-stable`. -3. If you have drank the `meson` koolaid, look at `.ci/build-win32.sh` to see how to - invoke `meson` now, or just run that script. Otherwise, here's how to use the - old trusty autotools instead: +2. Install the `mingw-w64` cross-compiler. - a) Install dependencies. - - Fedora, 32bit: `dnf install mingw32-glib2 mingw32-cairo mingw32-freetype` - - Fedora, 64bit: `dnf install mingw64-glib2 mingw64-cairo mingw64-freetype` + - Fedora, 32bit: `dnf install mingw32-gcc-c++` + - Fedora, 64bit: `dnf install mingw64-gcc-c++` + - Debian: `apt install g++-mingw-w64` + - Mac: `brew install mingw-w64` - b) Configure: - - `NOCONFIGURE=1 ./autogen.sh && mkdir winbuild && cd winbuild` - - 32bit: `../mingw-configure.sh i686` - - 64bit: `../mingw-configure.sh x86_64` +3. Install dependencies. - c) Build as usual: - - make + - Fedora, 32bit: `dnf install mingw32-glib2 mingw32-cairo mingw32-freetype` + - Fedora, 64bit: `dnf install mingw64-glib2 mingw64-cairo mingw64-freetype` - d) Configure your wine to find system mingw libraries. See: - https://fedoraproject.org/wiki/MinGW/Configure_wine +Or you could simply pull them all in one go with: -Now you can use `hb-shape` by `(cd win32build/util && wine hb-shape.exe)` -but if you like to shape with the Microsoft Uniscribe: + - Fedora, 32bit: `dnf install mingw32-harfbuzz` + - Fedora, 64bit: `dnf install mingw64-harfbuzz` -4. Bring a 32bit version of `usp10.dll` for yourself from `C:\Windows\SysWOW64\usp10.dll` of your - Windows installation (assuming you have a 64-bit installation, otherwise - `C:\Windows\System32\usp10.dll`) that it is not a DirectWrite proxy - ([for more info](https://en.wikipedia.org/wiki/Uniscribe)). - Rule of thumb, your `usp10.dll` should have a size more than 500kb, otherwise - it is designed to work with DirectWrite which Wine can't work with its original one. - You want a Uniscribe from Windows 7 or older. +If you cannot find these packages for your distribution, or you are on macOS, +you can skip to the next step, as meson will automatically download and build +the dependencies for you. - Put the DLL in the folder you are going to run the next command, +4. If you are familiar with `meson`, you can use the cross-compile files we +provide to find your way around. Read until the end of this section before +deciding which one to use. -5. `WINEDLLOVERRIDES="usp10=n" wine hb-shape.exe fontname.ttf -u 0061,0062,0063 --shaper=uniscribe` + - 32bit: `meson --cross-file=.ci/win32-cross-file.txt build-win -Dglib-enabled -Dcairo=enabled -Dgdi=enabled -Ddirectwrite=enabled` + - 64bit: `meson --cross-file=.ci/win64-cross-file.txt build-win -Dglib-enabled -Dcairo=enabled -Dgdi=enabled -Ddirectwrite=enabled` -(`0061,0062,0063` means `abc`, use test/shaping/hb-unicode-decode to generate ones you need) +In which case, you will proceed to run `ninja` as usual to build: -When you have built that, you can test HarfBuzz's native shaper against Uniscribe -following these instructions: + - `ninja -C build-win` - https://github.com/harfbuzz/harfbuzz/issues/3671 +Or you can simply invoke the scripts we provide for our Continuous Integration +system, to configure and build HarfBuzz for you. This is the easiest way to +build HarfBuzz for Windows and how we build our Windows binaries: + + - 32bit: `./.ci/build-win.sh 32 && ln -s build-win32 build-win` + - 64bit: `./.ci/build-win.sh 64 && ln -s build-win64 build-win` + +This might take a while, since, if you do not have the dependencies installed, +meson will download and build them for you. + +5. If everything succeeds, you should have the `hb-shape.exe`, `hb-view.exe`, +`hb-subset.exe`, and `hb-info.exe` executables in `build-win/util`. + +6. Configure your wine to find system mingw libraries. While there, set it also +to find the built HarfBuzz DLLs: + + - Fedora, 32bit: `export WINEPATH="$HOME/harfbuzz/build-win/src;/usr/i686-w64-mingw32/sys-root/mingw/bin"` + - Fedora, 64bit: `export WINEPATH="$HOME/harfbuzz/build-win/src;/usr/x86_64-w64-mingw32/sys-root/mingw/bin"` + - Other systems: `export WINEPATH="$HOME/harfbuzz/build-win/src"` + +Adjust for the path where you have built HarfBuzz. You might want to add this +to your `.bashrc` or `.zshrc` file. + +7. Run the `hb-shape` executable under Wine: + + - `wine build-win/util/hb-shape.exe perf/fonts/Roboto-Regular.ttf Test` + +You probably will get lots of Wine warnings, but if all works fine, you +should see: +``` +[gid57=0+1123|gid74=1+1086|gid88=2+1057|gid89=3+670] +``` + +You can make Wine less verbose, without hiding all errors, by setting: + + - `export WINEDEBUG=fixme-all,warn-all,err-plugplay,err-seh,err-rpc,err-ntoskrnl,err-winediag,err-systray,err-hid` + +Add this to your `.bashrc` or `.zshrc` file as well. + +Next, let's try some non-Latin text. Unfortunately, the command-line parsing of +our cross-compiled glib is not quite Unicode-aware, at least when run under +Wine. So you will need to find some other way to feed Unicode text to the +shaper. There are three different ways you can try: + + - `echo حرف | wine build-win/util/hb-shape.exe perf/fonts/Amiri-Regular.ttf` + - `wine build-win/util/hb-shape.exe perf/fonts/Amiri-Regular.ttf -u 062D,0631,0641` + - `wine build-win/util/hb-shape.exe perf/fonts/Amiri-Regular.ttf --text-file harf.txt` + +To get the Unicode codepoints for a string, you can use the `hb-unicode-decode` +utility: +``` +$ test/shape/hb-unicode-decode حرف +U+062D,U+0631,U+0641 +``` + +8. Next, let's try the `hb-view` utility. By default, `hb-view` outputs ANSI text, +which Wine will not display correctly. You can use the `-o` option to redirect the +output to a file, or just redirect the output using the shell, which will produce +a PNG file. + + - `wine build-win/util/hb-view.exe perf/fonts/Roboto-Regular.ttf Test > test.png` + +9. If you are on Linux and your Wine has configured itself as the processor for +the EXE files (called `binfmt` in Linux), you can run the executables directly: + + - `build-win/util/hb-shape.exe perf/fonts/Roboto-Regular.ttf Test` + +If that does not work, you can use the `wine` command as shown above. + +10. You can try running the test suite. If on Linux with `binfmt` enabled, you can +run the tests directly: + + - `ninja -C build-win test` + +If not, you might need to reconfigure the build directory to tell meson to use +Wine to run the tests. This part needs improvement, but for now: edit the +cross-file you used to build HarfBuzz and uncomment the `exe_wrapper` line: + + - 32bit: `.ci/win32-cross-file.txt` + - 64bit: `.ci/win64-cross-file.txt` + +Then go back to step 4 above and rebuild HarfBuzz with the `exe_wrapper` set. +If all goes well, tests should run with the above `ninja` command. If all is +well, you should probably see over 300 tests pass, some skipped, and just the +`directwrite` test fail. + +The reason the `directwrite` test fails is that we are running against the +Wine-provided DirectWrite DLL, which is an incomplete reimplementation of the +DirectWrite API by Wine, and not the real thing. If you want to test the +Uniscribe or DirectWrite shapers against the real Uniscribe / DirectWrite, you +can follow the instructions below. + +11. Uniscribe: Assuming a 32bit build for now. Bring a 32bit version of +`usp10.dll` for yourself from `C:\Windows\SysWOW64\usp10.dll` of your Windows +installation (assuming you have a 64-bit installation, otherwise +`C:\Windows\System32\usp10.dll`). You want one from Windows 7 or earlier. +One that is not just a proxy for `textshaping.dll`. Rule of thumb, your +`usp10.dll` should have a size more than 500kb. Put the file in +`build-win/src`. + +You can now tell wine to use the native `usp10.dll`: + + - `export WINEDLLOVERRIDES="usp10=n"` + - `wine build-win/util/hb-shape.exe perf/fonts/Roboto-Regular.ttf Test --shaper=uniscribe` + +12. DirectWrite: You can use the same method to test the DirectWrite shaper +against the native DirectWrite DLL. Try with a 64bit build this time. Bring +`textshaping.dll`, `dwrite.dll`, and `usp10.dll` from your Windows installation +(`C:\Windows\System32`) to `build-win/src`. You can now tell wine to use the +native DirectWrite: + + - `export WINEDLLOVERRIDES="textshaping,dwrite,usp10=n"` + - `wine build-win/util/hb-shape.exe perf/fonts/Roboto-Regular.ttf Test --shaper=directwrite` + +If all works well, you should be able to rerun the tests and see all pass this time. + +13. For some old instructions on how to test HarfBuzz's native Indic shaper against +Uniscribe, see: https://github.com/harfbuzz/harfbuzz/issues/3671 + +14. That's it! If you made it this far, you are now able to develop and test +HarfBuzz on Windows, from Linux or macOS. Enjoy!