Add hb_gdi_face_create API
authorEbrahim Byagowi <ebrahim@gnu.org>
Tue, 16 Jul 2019 17:57:01 +0000 (22:27 +0430)
committerBehdad Esfahbod <behdad@behdad.org>
Sun, 21 Jul 2019 21:22:19 +0000 (14:22 -0700)
Based on Konstantin Ritt work posted on mailing list

12 files changed:
CMakeLists.txt
appveyor.yml
configure.ac
docs/harfbuzz-sections.txt
src/Makefile.am
src/Makefile.sources
src/harfbuzz.cc
src/hb-directwrite.cc
src/hb-gdi.cc [new file with mode: 0644]
src/hb-gdi.h [new file with mode: 0644]
src/hb-uniscribe.cc
src/hb.hh

index c41579c..ac857ef 100644 (file)
@@ -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)
index 236bb1b..6daf8d2 100644 (file)
@@ -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\
index 09ce4e6..cebb10a 100644 (file)
@@ -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:
index f23dcd1..43fd761 100644 (file)
@@ -370,6 +370,11 @@ hb_ft_font_set_funcs
 </SECTION>
 
 <SECTION>
+<FILE>hb-gdi</FILE>
+hb_gdi_face_create
+</SECTION>
+
+<SECTION>
 <FILE>hb-glib</FILE>
 hb_glib_get_unicode_funcs
 hb_glib_script_from_script
index 1e79483..54e4a02 100644 (file)
@@ -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 | \
index e8d5bc5..4e84d86 100644 (file)
@@ -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
 
index 26cfac1..e399137 100644 (file)
@@ -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"
index 810c5e5..c14e9d2 100644 (file)
@@ -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 (file)
index 0000000..526f1cd
--- /dev/null
@@ -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 (file)
index 0000000..68cc439
--- /dev/null
@@ -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 <windows.h>
+
+HB_BEGIN_DECLS
+
+HB_EXTERN hb_face_t *
+hb_gdi_face_create (HFONT hfont);
+
+HB_END_DECLS
+
+#endif /* HB_GDI_H */
index b113ed4..289a347 100644 (file)
  * 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,
index f8b5e70..0790de2 100644 (file)
--- 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.