From cfc3157868f691b70c2f0a6daa3c387ca6ef42a9 Mon Sep 17 00:00:00 2001
From: Tor Lillqvist <tml@collabora.com>
Date: Tue, 10 Nov 2015 00:20:42 +0200
Subject: [PATCH 1/3] Port glyphy-demo to Windows

You will need glew and freeglut to build and run it.

I have a VS solution for glyphy-demo, but did not commit that as I did
not bother to do it "properly", with different projects for the
library and the demo executable, Release and Debug configurations etc.
---
 demo/demo-buffer.cc  |  11 ++++
 demo/demo-common.h   |   6 ++
 demo/demo-font.cc    | 131 +++++++++++++++++++++++++++++++++++---------
 demo/demo-font.h     |  21 ++++++-
 demo/demo-view.cc    |   3 +-
 demo/glyphy-demo.cc  | 134 ++++++++++++++++++++++++++++++++++++++++++++-
 src/Makefile.am      |   1 +
 src/glyphy-windows.h | 152 +++++++++++++++++++++++++++++++++++++++++++++++++++
 8 files changed, 429 insertions(+), 30 deletions(-)
 create mode 100755 src/glyphy-windows.h

diff --git a/demo/demo-buffer.cc b/demo/demo-buffer.cc
index 698f4ee..8ce5b34 100644
--- a/demo/demo-buffer.cc
+++ b/demo/demo-buffer.cc
@@ -106,7 +106,11 @@ demo_buffer_add_text (demo_buffer_t        *buffer,
 		      demo_font_t          *font,
 		      double                font_size)
 {
+#ifndef _WIN32
   FT_Face face = demo_font_get_face (font);
+#else
+  HDC hdc = demo_font_get_face (font);
+#endif
   glyphy_point_t top_left = buffer->cursor;
   buffer->cursor.y += font_size /* * font->ascent */;
   unsigned int unicode;
@@ -138,7 +142,14 @@ demo_buffer_add_text (demo_buffer_t        *buffer,
       continue;
     }
 
+#ifndef _WIN32
     unsigned int glyph_index = FT_Get_Char_Index (face, unicode);
+#else
+    wchar_t wc = unicode; /* FIXME: What about non-BMP chars? */
+    WORD glyph_index;
+    if (GetGlyphIndicesW (hdc, &wc, 1, &glyph_index, GGI_MARK_NONEXISTING_GLYPHS) == GDI_ERROR)
+      die ("GetGlyphIndicesW failed");
+#endif
     glyph_info_t gi;
     demo_font_lookup_glyph (font, glyph_index, &gi);
 
diff --git a/demo/demo-common.h b/demo/demo-common.h
index dd0feb9..da56a88 100644
--- a/demo/demo-common.h
+++ b/demo/demo-common.h
@@ -44,6 +44,12 @@
 #  define HAVE_GLUT 1
 #endif
 
+#ifdef _WIN32
+#  define HAVE_GL 1
+#  define HAVE_GLEW 1
+#  define HAVE_GLUT 1
+#endif
+
 /* Get Glew out of the way. */
 #ifdef HAVE_GLEW
 #  include <GL/glew.h>
diff --git a/demo/demo-font.cc b/demo/demo-font.cc
index 4ed4b53..b43b1e3 100644
--- a/demo/demo-font.cc
+++ b/demo/demo-font.cc
@@ -22,19 +22,30 @@
 
 #include "demo-font.h"
 
+#ifndef _WIN32
 #include <glyphy-freetype.h>
+#endif
 
-#include <ext/hash_map>
-
-using namespace __gnu_cxx; /* This is ridiculous */
+#ifdef _WIN32
+#include <glyphy-windows.h>
+#endif
 
+#include <map>
+#include <vector>
 
-typedef hash_map<unsigned int, glyph_info_t> glyph_cache_t;
+typedef std::map<unsigned int, glyph_info_t> glyph_cache_t;
 
 struct demo_font_t {
   unsigned int   refcount;
 
+#ifndef _WIN32
   FT_Face        face;
+#endif
+
+#ifdef _WIN32
+  HDC            face; /* A memory DC that has the font instance selected into it */
+#endif
+
   glyph_cache_t *glyph_cache;
   demo_atlas_t  *atlas;
   glyphy_arc_accumulator_t *acc;
@@ -48,7 +59,13 @@ struct demo_font_t {
 };
 
 demo_font_t *
-demo_font_create (FT_Face       face,
+demo_font_create (
+#ifndef _WIN32
+		  FT_Face       face,
+#endif
+#ifdef _WIN32
+		  HDC           face,
+#endif
 		  demo_atlas_t *atlas)
 {
   demo_font_t *font = (demo_font_t *) calloc (1, sizeof (demo_font_t));
@@ -88,7 +105,12 @@ demo_font_destroy (demo_font_t *font)
 }
 
 
+#ifndef _WIN32
 FT_Face
+#endif
+#ifdef _WIN32
+HDC
+#endif
 demo_font_get_face (demo_font_t *font)
 {
   return font->face;
@@ -103,27 +125,28 @@ demo_font_get_atlas (demo_font_t *font)
 
 static glyphy_bool_t
 accumulate_endpoint (glyphy_arc_endpoint_t         *endpoint,
-		     vector<glyphy_arc_endpoint_t> *endpoints)
+		     std::vector<glyphy_arc_endpoint_t> *endpoints)
 {
   endpoints->push_back (*endpoint);
   return true;
 }
 
 static void
-encode_ft_glyph (demo_font_t      *font,
-		 unsigned int      glyph_index,
-		 double            tolerance_per_em,
-		 glyphy_rgba_t    *buffer,
-		 unsigned int      buffer_len,
-		 unsigned int     *output_len,
-		 unsigned int     *nominal_width,
-		 unsigned int     *nominal_height,
-		 glyphy_extents_t *extents,
-		 double           *advance)
+encode_glyph (demo_font_t      *font,
+	      unsigned int      glyph_index,
+	      double            tolerance_per_em,
+	      glyphy_rgba_t    *buffer,
+	      unsigned int      buffer_len,
+	      unsigned int     *output_len,
+	      unsigned int     *nominal_width,
+	      unsigned int     *nominal_height,
+	      glyphy_extents_t *extents,
+	      double           *advance)
 {
 /* Used for testing only */
 #define SCALE  (1. * (1 << 0))
 
+#ifndef _WIN32
   FT_Face face = font->face;
   if (FT_Err_Ok != FT_Load_Glyph (face,
 				  glyph_index,
@@ -141,7 +164,7 @@ encode_ft_glyph (demo_font_t      *font,
   unsigned int upem = face->units_per_EM;
   double tolerance = upem * tolerance_per_em; /* in font design units */
   double faraway = double (upem) / (MIN_FONT_SIZE * M_SQRT2);
-  vector<glyphy_arc_endpoint_t> endpoints;
+  std::vector<glyphy_arc_endpoint_t> endpoints;
 
   glyphy_arc_accumulator_reset (font->acc);
   glyphy_arc_accumulator_set_tolerance (font->acc, tolerance);
@@ -151,6 +174,55 @@ encode_ft_glyph (demo_font_t      *font,
 
   if (FT_Err_Ok != glyphy_freetype(outline_decompose) (&face->glyph->outline, font->acc))
     die ("Failed converting glyph outline to arcs");
+#endif
+
+#ifdef _WIN32
+  HDC hdc = font->face;
+
+  GLYPHMETRICS glyph_metrics;
+  MAT2 matrix;
+
+  matrix.eM11.value = 1;
+  matrix.eM11.fract = 0;
+  matrix.eM12.value = 0;
+  matrix.eM12.fract = 0;
+  matrix.eM21.value = 0;
+  matrix.eM21.fract = 0;
+  matrix.eM22.value = 1;
+  matrix.eM22.fract = 0;
+
+  DWORD size = GetGlyphOutlineW (hdc, glyph_index, GGO_NATIVE|GGO_GLYPH_INDEX, &glyph_metrics, 0, NULL, &matrix);
+  if (size == GDI_ERROR)
+    die ("GetGlyphOutlineW failed");
+  std::vector<char> buf(size);
+  size = GetGlyphOutlineW (hdc, glyph_index, GGO_NATIVE|GGO_GLYPH_INDEX, &glyph_metrics, size, buf.data(), &matrix);
+  if (size == GDI_ERROR)
+    die ("GetGlyphOutlineW failed");
+
+  size = GetGlyphOutlineW (hdc, glyph_index, GGO_METRICS|GGO_GLYPH_INDEX, &glyph_metrics, 0, NULL, &matrix);
+  if (size == GDI_ERROR)
+    die ("GetGlyphOutlineW failed");
+
+  OUTLINETEXTMETRICW outline_text_metric;
+  if (!GetOutlineTextMetricsW (hdc, sizeof (OUTLINETEXTMETRICW), &outline_text_metric))
+    die ("GetOutlineTextMetricsW failed");
+
+  unsigned int upem = outline_text_metric.otmEMSquare;
+  double tolerance = upem * tolerance_per_em; /* in font design units */
+  double faraway = double (upem) / (MIN_FONT_SIZE * M_SQRT2);
+  std::vector<glyphy_arc_endpoint_t> endpoints;
+
+  fprintf(stderr, "upem=%u tolerance=%f faraway=%f\n", upem, tolerance, faraway);
+
+  glyphy_arc_accumulator_reset (font->acc);
+  glyphy_arc_accumulator_set_tolerance (font->acc, tolerance);
+  glyphy_arc_accumulator_set_callback (font->acc,
+				       (glyphy_arc_endpoint_accumulator_callback_t) accumulate_endpoint,
+				       &endpoints);
+
+  if (0 != glyphy_windows(outline_decompose) ((TTPOLYGONHEADER *) buf.data(), buf.size(), font->acc))
+    die ("Failed converting glyph outline to arcs");
+#endif
 
   assert (glyphy_arc_accumulator_get_error (font->acc) <= tolerance);
 
@@ -192,7 +264,14 @@ encode_ft_glyph (demo_font_t      *font,
   glyphy_extents_scale (extents, 1. / upem, 1. / upem);
   glyphy_extents_scale (extents, SCALE, SCALE);
 
+#ifndef _WIN32
   *advance = face->glyph->metrics.horiAdvance / (double) upem;
+#endif
+
+#ifdef _WIN32
+  *advance = glyph_metrics.gmCellIncX / (double) upem; /* ??? */
+  fprintf(stderr, "======> Advance: %f\n", *advance);
+#endif
 
   if (0)
     LOGI ("gid%3u: endpoints%3d; err%3g%%; tex fetch%4.1f; mem%4.1fkb\n",
@@ -217,15 +296,15 @@ _demo_font_upload_glyph (demo_font_t *font,
   glyphy_rgba_t buffer[4096 * 16];
   unsigned int output_len;
 
-  encode_ft_glyph (font,
-		   glyph_index,
-		   TOLERANCE,
-		   buffer, ARRAY_LEN (buffer),
-		   &output_len,
-		   &glyph_info->nominal_w,
-		   &glyph_info->nominal_h,
-		   &glyph_info->extents,
-		   &glyph_info->advance);
+  encode_glyph (font,
+		glyph_index,
+		TOLERANCE,
+		buffer, ARRAY_LEN (buffer),
+		&output_len,
+		&glyph_info->nominal_w,
+		&glyph_info->nominal_h,
+		&glyph_info->extents,
+		&glyph_info->advance);
 
   glyph_info->is_empty = glyphy_extents_is_empty (&glyph_info->extents);
   if (!glyph_info->is_empty)
diff --git a/demo/demo-font.h b/demo/demo-font.h
index ddc45ed..d4e75ff 100644
--- a/demo/demo-font.h
+++ b/demo/demo-font.h
@@ -22,9 +22,17 @@
 #include "demo-common.h"
 #include "demo-atlas.h"
 
+#ifndef _WIN32
 #include <ft2build.h>
 #include FT_FREETYPE_H
+#endif
 
+#ifdef _WIN32
+#include <windows.h>
+#define DEFAULT_FONT "Calibri"
+#undef near
+#undef far
+#endif
 
 typedef struct {
   glyphy_extents_t extents;
@@ -40,7 +48,13 @@ typedef struct {
 typedef struct demo_font_t demo_font_t;
 
 demo_font_t *
-demo_font_create (FT_Face       face,
+demo_font_create (
+#ifndef _WIN32
+		  FT_Face       face,
+#endif
+#ifdef _WIN32
+		  HDC           hdc,
+#endif
 		  demo_atlas_t *atlas);
 
 demo_font_t *
@@ -50,7 +64,12 @@ void
 demo_font_destroy (demo_font_t *font);
 
 
+#ifndef _WIN32
 FT_Face
+#endif
+#ifdef _WIN32
+HDC
+#endif
 demo_font_get_face (demo_font_t *font);
 
 demo_atlas_t *
diff --git a/demo/demo-view.cc b/demo/demo-view.cc
index b60fc24..fee3e23 100644
--- a/demo/demo-view.cc
+++ b/demo/demo-view.cc
@@ -27,8 +27,9 @@ extern "C" {
 #include "matrix4x4.h"
 }
 
+#ifndef _WIN32
 #include <sys/time.h>
-
+#endif
 
 struct demo_view_t {
   unsigned int   refcount;
diff --git a/demo/glyphy-demo.cc b/demo/glyphy-demo.cc
index cf412cc..bc71dff 100644
--- a/demo/glyphy-demo.cc
+++ b/demo/glyphy-demo.cc
@@ -20,14 +20,15 @@
 #include <config.h>
 #endif
 
+#ifndef _WIN32
 #include <libgen.h>
+#include <unistd.h>
+#endif
 #include <stdio.h>
 #include <string.h>
-#include <unistd.h>
 #include <ctype.h>
 #include <stdlib.h>
 
-
 #include "demo-buffer.h"
 #include "demo-font.h"
 #include "demo-view.h"
@@ -39,6 +40,90 @@ static demo_buffer_t *buffer;
 #define WINDOW_W 700
 #define WINDOW_H 700
 
+#ifdef _WIN32
+
+static int isroot(const char *path)
+{
+  return ((strlen(path) == 1 && path[0] == '/') ||
+	  (strlen(path) == 3 && isalpha(path[0]) && path[1] == ':' && (path[2] == '/' || path[2] == '\\')));
+}
+
+static char *basename(char *path)
+{
+  if (path == NULL || *path == '\0')
+    return ".";
+
+  while ((path[strlen(path)-1] == '/' ||
+	  path[strlen(path)-1] == '\\') &&
+	 !isroot(path))
+    path[strlen(path)-1] = '\0';
+
+  if (isroot(path))
+    return path;
+
+  char *slash = strrchr(path, '/');
+  char *backslash = strrchr(path, '\\');
+
+  if (slash != NULL && (backslash == NULL || backslash < slash))
+    return slash + 1;
+  else if (backslash != NULL && (slash == NULL || slash < backslash))
+    return backslash + 1;
+  else
+    return path;
+}
+
+static int opterr = 1;
+static int optind = 1;
+static int optopt;
+static char *optarg;
+
+static int getopt(int argc, char *argv[], char *opts)
+{
+    static int sp = 1;
+    int c;
+    char *cp;
+
+    if (sp == 1) {
+        if (optind >= argc ||
+            argv[optind][0] != '-' || argv[optind][1] == '\0')
+            return EOF;
+        else if (!strcmp(argv[optind], "--")) {
+            optind++;
+            return EOF;
+        }
+    }
+    optopt = c = argv[optind][sp];
+    if (c == ':' || !(cp = strchr(opts, c))) {
+        fprintf(stderr, ": illegal option -- %c\n", c);
+        if (argv[optind][++sp] == '\0') {
+            optind++;
+            sp = 1;
+        }
+        return '?';
+    }
+    if (*++cp == ':') {
+        if (argv[optind][sp+1] != '\0')
+            optarg = &argv[optind++][sp+1];
+        else if(++optind >= argc) {
+            fprintf(stderr, ": option requires an argument -- %c\n", c);
+            sp = 1;
+            return '?';
+        } else
+            optarg = argv[optind++];
+        sp = 1;
+    } else {
+        if (argv[optind][++sp] == '\0') {
+            sp = 1;
+            optind++;
+        }
+        optarg = NULL;
+    }
+
+    return c;
+}
+
+#endif
+
 static void
 reshape_func (int width, int height)
 {
@@ -161,6 +246,7 @@ main (int argc, char** argv)
   vu = demo_view_create (st);
   demo_view_print_help (vu);
 
+#ifndef _WIN32
   FT_Library ft_library;
   FT_Init_FreeType (&ft_library);
   FT_Face ft_face;
@@ -173,6 +259,42 @@ main (int argc, char** argv)
   if (!ft_face)
     die ("Failed to open font file");
   demo_font_t *font = demo_font_create (ft_face, demo_glstate_get_atlas (st));
+#endif
+
+#ifdef _WIN32
+  HDC hdc = CreateCompatibleDC (GetDC (NULL));
+  if (hdc == NULL)
+    die ("GetDC or CreateCompatibleDC failed");
+
+  /* First create an instance of the font at size 10 to get the OUTLINETEXTMETRIC from which to get
+   * the font's em unit. Then, to get an unmodified not grid-fitted glyph outline, create it anew at
+   * that size. That is  as the doc for GetGlyphOutline() suggests.
+   */
+  HFONT hfont = CreateFontA(10, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_TT_ONLY_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, FF_DONTCARE, font_path);
+  if (hfont == NULL)
+    die ("CreateFontA failed");
+
+  HFONT old_hfont = (HFONT) SelectObject (hdc, hfont);
+  if (old_hfont == NULL)
+    die ("SelectObject failed");
+
+  OUTLINETEXTMETRICW outline_text_metric;
+  if (!GetOutlineTextMetricsW (hdc, sizeof (OUTLINETEXTMETRICW), &outline_text_metric))
+    die ("GetOutlineTextMetricsW failed");
+
+  SelectObject (hdc, old_hfont);
+
+  hfont = CreateFontA (outline_text_metric.otmEMSquare, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_TT_ONLY_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, FF_DONTCARE, font_path);
+  if (hfont == NULL)
+    die ("CreateFontA failed");
+
+  old_hfont = (HFONT) SelectObject (hdc, hfont);
+  if (old_hfont == NULL)
+    die ("SelectObject failed");
+
+  demo_font_t *font = demo_font_create (hdc, demo_glstate_get_atlas (st));
+
+#endif
 
   buffer = demo_buffer_create ();
   glyphy_point_t top_left = {0, 0};
@@ -187,8 +309,16 @@ main (int argc, char** argv)
   demo_buffer_destroy (buffer);
   demo_font_destroy (font);
 
+#ifndef _WIN32
   FT_Done_Face (ft_face);
   FT_Done_FreeType (ft_library);
+#endif
+
+#ifdef _WIN32
+  SelectObject (hdc, old_hfont);
+  DeleteObject (hfont);
+  DeleteDC (hdc);
+#endif
 
   demo_view_destroy (vu);
   demo_glstate_destroy (st);
diff --git a/src/Makefile.am b/src/Makefile.am
index 004afd3..ecb76e0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -32,6 +32,7 @@ libglyphy_la_SOURCES = \
 PUBLICHEADERS = \
 	glyphy.h \
 	glyphy-freetype.h \
+	glyphy-windows.h \
 	$(NULL)
 SHADERS = \
 	glyphy-common.glsl \
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -32,6 +32,7 @@ libglyphy_la_SOURCES = \
 PUBLICHEADERS = \
 	glyphy.h \
 	glyphy-freetype.h \
+	glyphy-windows.h \
 	$(NULL)
 
 SHADERS = \
diff --git a/src/glyphy-windows.h b/src/glyphy-windows.h
new file mode 100755
index 0000000..b3c11c8
--- /dev/null
+++ b/src/glyphy-windows.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2012 Google, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Google Author(s): Behdad Esfahbod, Maysum Panju
+ */
+
+/* Intentionally doesn't have include guards */
+
+#include "glyphy.h"
+
+#include <windows.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifndef GLYPHY_WINDOWS__PREFIX
+#define GLYPHY_WINDOWS_PREFIX glyphy_windows_
+#endif
+
+#ifndef glyphy_windows
+#define glyphy_windows(name) GLYPHY_PASTE (GLYPHY_WINDOWS_PREFIX, name)
+#endif
+
+static double fixed_to_double(FIXED f)
+{
+  return f.value + f.fract / double(0x10000);
+}
+
+static int
+glyphy_windows(move_to) (const POINTFX            *to,
+			 glyphy_arc_accumulator_t *acc)
+{
+  glyphy_point_t p1 = {fixed_to_double(to->x), fixed_to_double(to->y)};
+  glyphy_arc_accumulator_close_path (acc);
+  glyphy_arc_accumulator_move_to (acc, &p1);
+  return glyphy_arc_accumulator_successful (acc) ? 0 : -1;
+}
+
+static int
+glyphy_windows(line_to) (const POINTFX            *to,
+			 glyphy_arc_accumulator_t *acc)
+{
+  glyphy_point_t p1 = {fixed_to_double(to->x), fixed_to_double(to->y)};
+  glyphy_arc_accumulator_line_to (acc, &p1);
+  return glyphy_arc_accumulator_successful (acc) ? 0 : -1;
+}
+
+static int
+glyphy_windows(conic_to) (const POINTFX            *control,
+			  const glyphy_point_t     *p2,
+			  glyphy_arc_accumulator_t *acc)
+{
+  glyphy_point_t p1 = {fixed_to_double(control->x), fixed_to_double(control->y)};
+  glyphy_arc_accumulator_conic_to (acc, &p1, p2);
+  return glyphy_arc_accumulator_successful (acc) ? 0 : -1;
+}
+
+/* See https://support.microsoft.com/en-us/kb/87115 */
+
+static int
+glyphy_windows(outline_decompose) (const TTPOLYGONHEADER    *outline,
+				   size_t                    outline_size,
+				   glyphy_arc_accumulator_t *acc)
+{
+  const TTPOLYGONHEADER *polygon = outline;
+  const TTPOLYGONHEADER *outline_end = (const TTPOLYGONHEADER*) ((char *)outline + outline_size);
+
+  int polygon_count = 0;
+  while (polygon < outline_end)
+  {
+    if (((char *)polygon + polygon->cb) > (char *) outline_end)
+      die ("TTPOLYGONHEADER record too large for enclosing data");
+
+    assert(polygon->dwType == TT_POLYGON_TYPE);
+
+    if (glyphy_windows(move_to) (&polygon->pfxStart, acc) == -1)
+      return -1;
+
+    const TTPOLYCURVE *curve = (const TTPOLYCURVE*) (polygon + 1);
+    const TTPOLYCURVE *curve_end = (const TTPOLYCURVE*) ((char *)polygon + polygon->cb);
+    int curve_count = 0;
+    while (curve < curve_end)
+    {
+      if (((char *) &curve->apfx[curve->cpfx]) > (char *) curve_end)
+	die ("TTPOLYCURVE record too large for enclosing TTPOLYGONHEADER\n");
+
+      switch (curve->wType)
+      {
+      case TT_PRIM_LINE:
+	{
+	  int i;
+	  for (i = 0; i < curve->cpfx; i++) {
+	    if (glyphy_windows(line_to) (&curve->apfx[i], acc) == -1)
+	      return -1;
+	  }
+
+	  /* A final TT_PRIM_LINE in a contour automatically closes to the contour start */
+	  if ((const TTPOLYCURVE *) ((char *) &curve->apfx[curve->cpfx]) == curve_end)
+	    if (glyphy_windows(line_to) (&polygon->pfxStart, acc) == -1)
+	      return -1;
+	}
+	break;
+      case TT_PRIM_QSPLINE:
+	{
+	  int i = 0;
+	  while (i < curve->cpfx) {
+	    const POINTFX *control = &curve->apfx[i];
+	    i++;
+	    const POINTFX *p2 = &curve->apfx[i];
+	    glyphy_point_t p2pt = {fixed_to_double(p2->x), fixed_to_double(p2->y)};
+	    if (i == curve->cpfx - 1) {
+	      i++;
+	    } else {
+	      p2pt.x = (p2pt.x + fixed_to_double(control->x)) / 2;
+	      p2pt.y = (p2pt.y + fixed_to_double(control->y)) / 2;
+	    }
+	    if (glyphy_windows(conic_to) (control, &p2pt, acc) == -1)
+	      return -1;
+	  }
+	  /* If the last point of the contour was not the start point, draw a closing line to it */
+	  if ((const TTPOLYCURVE *) ((char *) &curve->apfx[curve->cpfx]) == curve_end)
+	    if (glyphy_windows(line_to) (&polygon->pfxStart, acc) == -1)
+	      return -1;
+	}
+	break;
+      default:
+	die ("Unexpected record in TTPOLYCURVE");
+      }
+      curve = (const TTPOLYCURVE *) ((char *) &curve->apfx[curve->cpfx]);
+    }
+    polygon = (const TTPOLYGONHEADER *) curve_end;
+  }
+  return 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
-- 
2.4.3

From 6d4196a2dc59324d14d3d4d721929e851277da97 Mon Sep 17 00:00:00 2001
From: Tor Lillqvist <tml@collabora.com>
Date: Tue, 10 Nov 2015 13:35:17 +0200
Subject: [PATCH 2/3] Bin leftover printf

---
 demo/demo-font.cc | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/demo/demo-font.cc b/demo/demo-font.cc
index b43b1e3..c28778e 100644
--- a/demo/demo-font.cc
+++ b/demo/demo-font.cc
@@ -212,8 +212,6 @@ encode_glyph (demo_font_t      *font,
   double faraway = double (upem) / (MIN_FONT_SIZE * M_SQRT2);
   std::vector<glyphy_arc_endpoint_t> endpoints;
 
-  fprintf(stderr, "upem=%u tolerance=%f faraway=%f\n", upem, tolerance, faraway);
-
   glyphy_arc_accumulator_reset (font->acc);
   glyphy_arc_accumulator_set_tolerance (font->acc, tolerance);
   glyphy_arc_accumulator_set_callback (font->acc,
@@ -270,7 +268,6 @@ encode_glyph (demo_font_t      *font,
 
 #ifdef _WIN32
   *advance = glyph_metrics.gmCellIncX / (double) upem; /* ??? */
-  fprintf(stderr, "======> Advance: %f\n", *advance);
 #endif
 
   if (0)
-- 
2.4.3

From 45ad6c9336e78b0fc5aeec4cd7d602333751a93f Mon Sep 17 00:00:00 2001
From: Tor Lillqvist <tml@collabora.com>
Date: Thu, 19 Nov 2015 15:31:04 +0200
Subject: [PATCH] Bin two initialized but unused variables

---
 src/glyphy-windows.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/glyphy-windows.h b/src/glyphy-windows.h
index b3c11c8..5912073 100644
--- a/src/glyphy-windows.h
+++ b/src/glyphy-windows.h
@@ -79,7 +79,6 @@ glyphy_windows(outline_decompose) (const TTPOLYGONHEADER    *outline,
   const TTPOLYGONHEADER *polygon = outline;
   const TTPOLYGONHEADER *outline_end = (const TTPOLYGONHEADER*) ((char *)outline + outline_size);
 
-  int polygon_count = 0;
   while (polygon < outline_end)
   {
     if (((char *)polygon + polygon->cb) > (char *) outline_end)
@@ -92,7 +91,6 @@ glyphy_windows(outline_decompose) (const TTPOLYGONHEADER    *outline,
 
     const TTPOLYCURVE *curve = (const TTPOLYCURVE*) (polygon + 1);
     const TTPOLYCURVE *curve_end = (const TTPOLYCURVE*) ((char *)polygon + polygon->cb);
-    int curve_count = 0;
     while (curve < curve_end)
     {
       if (((char *) &curve->apfx[curve->cpfx]) > (char *) curve_end)
-- 
2.5.0

