diff --git a/CMakeLists.txt b/CMakeLists.txt index c41579c1c..ac857ef8f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,6 +43,7 @@ if (APPLE) endif () if (WIN32) option(HB_HAVE_UNISCRIBE "Enable Uniscribe shaper backend on Windows" OFF) + option(HB_HAVE_GDI "Enable GDI integration helpers on Windows" OFF) option(HB_HAVE_DIRECTWRITE "Enable DirectWrite shaper backend on Windows" OFF) endif () option(HB_BUILD_UTILS "Build harfbuzz utils, needs cairo, freetype, and glib properly be installed" OFF) @@ -77,6 +78,7 @@ if (HB_CHECK) set (HB_HAVE_GRAPHITE2 ON) if (WIN32) set (HB_HAVE_UNISCRIBE ON) + set (HB_HAVE_GDI ON) set (HB_HAVE_DIRECTWRITE ON) elseif (APPLE) set (HB_HAVE_CORETEXT ON) @@ -305,6 +307,12 @@ if (APPLE AND HB_HAVE_CORETEXT) endif () endif () +if (WIN32 AND HB_HAVE_GDI) + add_definitions(-DHAVE_GDI) + list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-gdi.h) + list(APPEND THIRD_PARTY_LIBS gdi32) +endif () + if (WIN32 AND HB_HAVE_UNISCRIBE) add_definitions(-DHAVE_UNISCRIBE) list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-uniscribe.h) diff --git a/appveyor.yml b/appveyor.yml index 236bb1b12..6daf8d225 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -73,7 +73,7 @@ build_script: - 'if "%compiler%"=="msvc2" cmake --build build --config %configuration%' - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "curl https://raw.githubusercontent.com/mirror/mingw-w64/023eb04c396d4e8d8fcf604cfababc53dae13398/mingw-w64-headers/include/dwrite_1.h > %MINGW_PREFIX%/%MINGW_CHOST%/include/dwrite_1.h"' - - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh --with-uniscribe --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 --with-directwrite --build=%MINGW_CHOST% --host=%MINGW_CHOST% --prefix=%MINGW_PREFIX%; make -j3 check || .ci/fail.sh"' + - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh --with-uniscribe --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 --with-directwrite --with-gdi --build=%MINGW_CHOST% --host=%MINGW_CHOST% --prefix=%MINGW_PREFIX%; make -j3 check || .ci/fail.sh"' cache: - c:\tools\vcpkg\installed\ diff --git a/configure.ac b/configure.ac index 09ce4e6ec..cebb10adf 100644 --- a/configure.ac +++ b/configure.ac @@ -361,6 +361,28 @@ AM_CONDITIONAL(HAVE_UNISCRIBE, $have_uniscribe) dnl =========================================================================== +AC_ARG_WITH(gdi, + [AS_HELP_STRING([--with-gdi=@<:@yes/no/auto@:>@], + [Provide GDI integration helpers @<:@default=no@:>@])],, + [with_gdi=no]) +have_gdi=false +if test "x$with_gdi" = "xyes" -o "x$with_gdi" = "xauto"; then + AC_CHECK_HEADERS(windows.h, have_gdi=true) +fi +if test "x$with_gdi" = "xyes" -a "x$have_gdi" != "xtrue"; then + AC_MSG_ERROR([gdi support requested but not found]) +fi +if $have_gdi; then + GDI_CFLAGS= + GDI_LIBS="-lgdi32" + AC_SUBST(GDI_CFLAGS) + AC_SUBST(GDI_LIBS) + AC_DEFINE(HAVE_GDI, 1, [Have GDI library]) +fi +AM_CONDITIONAL(HAVE_GDI, $have_gdi) + +dnl =========================================================================== + AC_ARG_WITH(directwrite, [AS_HELP_STRING([--with-directwrite=@<:@yes/no/auto@:>@], [Use the DirectWrite library (experimental) @<:@default=no@:>@])],, @@ -510,6 +532,7 @@ Additional shapers (the more the merrier): Platform shapers (not normally needed): CoreText: ${have_coretext} DirectWrite: ${have_directwrite} + GDI: ${have_gdi} Uniscribe: ${have_uniscribe} Other features: diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index f23dcd19b..43fd76115 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -369,6 +369,11 @@ hb_ft_font_get_load_flags hb_ft_font_set_funcs +
+hb-gdi +hb_gdi_face_create +
+
hb-glib hb_glib_get_unicode_funcs diff --git a/src/Makefile.am b/src/Makefile.am index 1e79483c9..54e4a02cf 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -82,6 +82,13 @@ HBSOURCES += $(HB_DIRECTWRITE_sources) HBHEADERS += $(HB_DIRECTWRITE_headers) endif +if HAVE_GDI +HBCFLAGS += $(GDI_CXXFLAGS) +HBNONPCLIBS += $(GDI_LIBS) +HBSOURCES += $(HB_GDI_sources) +HBHEADERS += $(HB_GDI_headers) +endif + if HAVE_CORETEXT HBCFLAGS += $(CORETEXT_CFLAGS) HBNONPCLIBS += $(CORETEXT_LIBS) @@ -313,6 +320,7 @@ harfbuzz.cc: Makefile.sources $(HB_FT_sources) \ $(HB_GRAPHITE2_sources) \ $(HB_UNISCRIBE_sources) \ + $(HB_GDI_sources) \ $(HB_DIRECTWRITE_sources) \ $(HB_CORETEXT_sources) \ ; do echo '#include "'$$f'"'; done | \ diff --git a/src/Makefile.sources b/src/Makefile.sources index e8d5bc593..4e84d869e 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -225,6 +225,9 @@ HB_CORETEXT_headers = hb-coretext.h HB_DIRECTWRITE_sources = hb-directwrite.cc HB_DIRECTWRITE_headers = hb-directwrite.h +HB_GDI_sources = hb-gdi.cc +HB_GDI_headers = hb-gdi.h + HB_UNISCRIBE_sources = hb-uniscribe.cc HB_UNISCRIBE_headers = hb-uniscribe.h diff --git a/src/harfbuzz.cc b/src/harfbuzz.cc index 26cfac1b4..e39913761 100644 --- a/src/harfbuzz.cc +++ b/src/harfbuzz.cc @@ -47,5 +47,6 @@ #include "hb-ft.cc" #include "hb-graphite2.cc" #include "hb-uniscribe.cc" +#include "hb-gdi.cc" #include "hb-directwrite.cc" #include "hb-coretext.cc" diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc index 810c5e553..c14e9d2be 100644 --- a/src/hb-directwrite.cc +++ b/src/hb-directwrite.cc @@ -539,11 +539,6 @@ protected: Run mRunHead; }; -static inline uint16_t hb_dw_uint16_swap (const uint16_t v) -{ return (v >> 8) | (v << 8); } -static inline uint32_t hb_dw_uint32_swap (const uint32_t v) -{ return (hb_dw_uint16_swap (v) << 16) | hb_dw_uint16_swap (v >> 16); } - /* * shaper */ @@ -653,7 +648,7 @@ _hb_directwrite_shape_full (hb_shape_plan_t *shape_plan, for (unsigned int i = 0; i < num_features; ++i) { typographic_features.features[i].nameTag = (DWRITE_FONT_FEATURE_TAG) - hb_dw_uint32_swap (features[i].tag); + hb_uint32_swap (features[i].tag); typographic_features.features[i].parameter = features[i].value; } } @@ -941,7 +936,7 @@ _hb_directwrite_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void * uint32_t length; void *table_context; BOOL exists; - if (!dw_face || FAILED (dw_face->TryGetFontTable (hb_dw_uint32_swap (tag), &data, + if (!dw_face || FAILED (dw_face->TryGetFontTable (hb_uint32_swap (tag), &data, &length, &table_context, &exists))) return nullptr; diff --git a/src/hb-gdi.cc b/src/hb-gdi.cc new file mode 100644 index 000000000..526f1cd9e --- /dev/null +++ b/src/hb-gdi.cc @@ -0,0 +1,73 @@ +/* + * Copyright © 2019 Ebrahim Byagowi + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#include "hb.hh" + +#ifdef HAVE_GDI + +#include "hb-gdi.h" + +static hb_blob_t * +_hb_gdi_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) +{ + char *buffer = nullptr; + DWORD length = 0; + + HDC hdc = GetDC (nullptr); + if (unlikely (!SelectObject (hdc, (HFONT) user_data))) goto fail; + + length = GetFontData (hdc, hb_uint32_swap (tag), 0, buffer, length); + if (unlikely (length == GDI_ERROR)) goto fail_with_releasedc; + + buffer = (char *) malloc (length); + if (unlikely (!buffer)) goto fail_with_releasedc; + length = GetFontData (hdc, hb_uint32_swap (tag), 0, buffer, length); + if (unlikely (length == GDI_ERROR)) goto fail_with_releasedc_and_free; + ReleaseDC (nullptr, hdc); + + return hb_blob_create ((const char *) buffer, length, HB_MEMORY_MODE_WRITABLE, buffer, free); + +fail_with_releasedc_and_free: + free (buffer); +fail_with_releasedc: + ReleaseDC (nullptr, hdc); +fail: + return hb_blob_get_empty (); +} + +/** + * hb_gdi_face_create: + * @hdc: a HFONT object. + * + * Return value: #hb_face_t object corresponding to the given input + * + * Since: REPLACEME + **/ +hb_face_t * +hb_gdi_face_create (HFONT hfont) +{ + return hb_face_create_for_tables (_hb_gdi_reference_table, (void *) hfont, nullptr); +} + +#endif diff --git a/src/hb-gdi.h b/src/hb-gdi.h new file mode 100644 index 000000000..68cc43917 --- /dev/null +++ b/src/hb-gdi.h @@ -0,0 +1,39 @@ +/* + * Copyright © 2019 Ebrahim Byagowi + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#ifndef HB_GDI_H +#define HB_GDI_H + +#include "hb.h" + +#include + +HB_BEGIN_DECLS + +HB_EXTERN hb_face_t * +hb_gdi_face_create (HFONT hfont); + +HB_END_DECLS + +#endif /* HB_GDI_H */ diff --git a/src/hb-uniscribe.cc b/src/hb-uniscribe.cc index b113ed4cf..289a3477f 100644 --- a/src/hb-uniscribe.cc +++ b/src/hb-uniscribe.cc @@ -58,13 +58,6 @@ * Functions for using HarfBuzz with the Windows fonts. **/ - -static inline uint16_t hb_uint16_swap (const uint16_t v) -{ return (v >> 8) | (v << 8); } -static inline uint32_t hb_uint32_swap (const uint32_t v) -{ return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); } - - typedef HRESULT (WINAPI *SIOT) /*ScriptItemizeOpenType*/( const WCHAR *pwcInChars, int cInChars, diff --git a/src/hb.hh b/src/hb.hh index f8b5e70a8..0790de2fd 100644 --- a/src/hb.hh +++ b/src/hb.hh @@ -476,6 +476,11 @@ static_assert ((sizeof (hb_var_int_t) == 4), ""); /* Size signifying variable-sized array */ #define VAR 1 +/* Endian swap, used in Windows related backends */ +static inline uint16_t hb_uint16_swap (const uint16_t v) +{ return (v >> 8) | (v << 8); } +static inline uint32_t hb_uint32_swap (const uint32_t v) +{ return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); } /* * Big-endian integers. Here because fundamental.