Imported Upstream version 0.9.40
[platform/upstream/harfbuzz.git] / src / hb-ft.cc
index 16bf51f..322f93a 100644 (file)
  *     In particular, FT_Get_Advance() without the NO_HINTING flag seems to be
  *     buggy.
  *
+ *     FreeType works in 26.6 mode.  Clients can decide to use that mode, and everything
+ *     would work fine.  However, we also abuse this API for performing in font-space,
+ *     but don't pass the correct flags to FreeType.  We just abuse the no-hinting mode
+ *     for that, such that no rounding etc happens.  As such, we don't set ppem, and
+ *     pass NO_HINTING around.  This seems to work best, until we go ahead and add a full
+ *     load_flags API.
+ *
  *   - We don't handle / allow for emboldening / obliqueing.
  *
  *   - In the future, we should add constructors to create fonts in font space?
@@ -70,12 +77,10 @@ hb_ft_get_glyph (hb_font_t *font HB_UNUSED,
 {
   FT_Face ft_face = (FT_Face) font_data;
 
-#ifdef HAVE_FT_FACE_GETCHARVARIANTINDEX
   if (unlikely (variation_selector)) {
     *glyph = FT_Face_GetCharVariantIndex (ft_face, unicode, variation_selector);
     return *glyph != 0;
   }
-#endif
 
   *glyph = FT_Get_Char_Index (ft_face, unicode);
   return *glyph != 0;
@@ -94,6 +99,9 @@ hb_ft_get_glyph_h_advance (hb_font_t *font HB_UNUSED,
   if (unlikely (FT_Get_Advance (ft_face, glyph, load_flags, &v)))
     return 0;
 
+  if (font->x_scale < 0)
+    v = -v;
+
   return (v + (1<<9)) >> 10;
 }
 
@@ -110,6 +118,9 @@ hb_ft_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
   if (unlikely (FT_Get_Advance (ft_face, glyph, load_flags, &v)))
     return 0;
 
+  if (font->y_scale < 0)
+    v = -v;
+
   /* Note: FreeType's vertical metrics grows downward while other FreeType coordinates
    * have a Y growing upward.  Hence the extra negation. */
   return (-v + (1<<9)) >> 10;
@@ -136,7 +147,7 @@ hb_ft_get_glyph_v_origin (hb_font_t *font HB_UNUSED,
                          void *user_data HB_UNUSED)
 {
   FT_Face ft_face = (FT_Face) font_data;
-  int load_flags = FT_LOAD_DEFAULT;
+  int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
 
   if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags)))
     return false;
@@ -146,6 +157,11 @@ hb_ft_get_glyph_v_origin (hb_font_t *font HB_UNUSED,
   *x = ft_face->glyph->metrics.horiBearingX -   ft_face->glyph->metrics.vertBearingX;
   *y = ft_face->glyph->metrics.horiBearingY - (-ft_face->glyph->metrics.vertBearingY);
 
+  if (font->x_scale < 0)
+    *x = -*x;
+  if (font->y_scale < 0)
+    *y = -*y;
+
   return true;
 }
 
@@ -185,7 +201,7 @@ hb_ft_get_glyph_extents (hb_font_t *font HB_UNUSED,
                         void *user_data HB_UNUSED)
 {
   FT_Face ft_face = (FT_Face) font_data;
-  int load_flags = FT_LOAD_DEFAULT;
+  int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
 
   if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags)))
     return false;
@@ -340,11 +356,7 @@ hb_ft_face_create (FT_Face           ft_face,
 
     blob = hb_blob_create ((const char *) ft_face->stream->base,
                           (unsigned int) ft_face->stream->size,
-                          /* TODO: We assume that it's mmap()'ed, but FreeType code
-                           * suggests that there are cases we reach here but font is
-                           * not mmapped.  For example, when mmap() fails.  No idea
-                           * how to deal with it better here. */
-                          HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE,
+                          HB_MEMORY_MODE_READONLY,
                           ft_face, destroy);
     face = hb_face_create (blob, ft_face->face_index);
     hb_blob_destroy (blob);
@@ -358,6 +370,22 @@ hb_ft_face_create (FT_Face           ft_face,
   return face;
 }
 
+/**
+ * hb_ft_face_create_referenced:
+ * @ft_face:
+ *
+ * 
+ *
+ * Return value: (transfer full): 
+ * Since: 1.0
+ **/
+hb_face_t *
+hb_ft_face_create_referenced (FT_Face ft_face)
+{
+  FT_Reference_Face (ft_face);
+  return hb_ft_face_create (ft_face, (hb_destroy_func_t) FT_Done_Face);
+}
+
 static void
 hb_ft_face_finalize (FT_Face ft_face)
 {
@@ -420,23 +448,43 @@ hb_ft_font_create (FT_Face           ft_face,
   hb_font_set_scale (font,
                     (int) (((uint64_t) ft_face->size->metrics.x_scale * (uint64_t) ft_face->units_per_EM + (1<<15)) >> 16),
                     (int) (((uint64_t) ft_face->size->metrics.y_scale * (uint64_t) ft_face->units_per_EM + (1<<15)) >> 16));
+#if 0 /* hb-ft works in no-hinting model */
   hb_font_set_ppem (font,
                    ft_face->size->metrics.x_ppem,
                    ft_face->size->metrics.y_ppem);
+#endif
 
   return font;
 }
 
+/**
+ * hb_ft_font_create_referenced:
+ * @ft_face:
+ *
+ * 
+ *
+ * Return value: (transfer full): 
+ * Since: 1.0
+ **/
+hb_font_t *
+hb_ft_font_create_referenced (FT_Face ft_face)
+{
+  FT_Reference_Face (ft_face);
+  return hb_ft_font_create (ft_face, (hb_destroy_func_t) FT_Done_Face);
+}
+
 
 /* Thread-safe, lock-free, FT_Library */
 
 static FT_Library ft_library;
 
-static inline
+#ifdef HB_USE_ATEXIT
+static
 void free_ft_library (void)
 {
   FT_Done_FreeType (ft_library);
 }
+#endif
 
 static FT_Library
 get_ft_library (void)
@@ -493,14 +541,19 @@ hb_ft_font_set_funcs (hb_font_t *font)
 
   FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE);
 
-  assert (font->y_scale >= 0);
   FT_Set_Char_Size (ft_face,
-                   font->x_scale, font->y_scale,
+                   abs (font->x_scale), abs (font->y_scale),
                    0, 0);
 #if 0
                    font->x_ppem * 72 * 64 / font->x_scale,
                    font->y_ppem * 72 * 64 / font->y_scale);
 #endif
+  if (font->x_scale < 0 || font->y_scale < 0)
+  {
+    FT_Matrix matrix = { font->x_scale < 0 ? -1 : +1, 0,
+                         0, font->y_scale < 0 ? -1 : +1};
+    FT_Set_Transform (ft_face, &matrix, NULL);
+  }
 
   ft_face->generic.data = blob;
   ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob;