]> granicus.if.org Git - imagemagick/commitdiff
https://github.com/ImageMagick/ImageMagick/pull/69.patch refactored
authorCristy <urban-warrior@imagemagick.org>
Wed, 23 Dec 2015 01:40:36 +0000 (20:40 -0500)
committerCristy <urban-warrior@imagemagick.org>
Wed, 23 Dec 2015 01:40:36 +0000 (20:40 -0500)
MagickCore/annotate.c

index a91e425efdc1e613ee9b0e1b3e17e6873565f78b..5708b31ecfe1c0351ce6cb8e0f10c58213e3ac4c 100644 (file)
 #  include <freetype/ftbbox.h>
 #endif /* defined(FT_BBOX_H) */
 #endif
+#if defined(MAGICKCORE_CTL_DELEGATE)
+#include <raqm.h>
+#else
+typedef struct _raqm_glyph_info_t
+{
+  int
+    index,
+    x_offset,
+    x_advance,
+    y_offset;
+
+  unsigned int
+    cluster;
+} raqm_glyph_info_t;
+
+typedef enum
+{
+  RAQM_DIRECTION_DEFAULT,
+  RAQM_DIRECTION_RTL,
+  RAQM_DIRECTION_LTR
+} raqm_direction_t;
+#endif
 \f
 /*
   Annotate semaphores.
@@ -999,6 +1021,53 @@ static MagickBooleanType RenderType(Image *image,const DrawInfo *draw_info,
 
 #if defined(MAGICKCORE_FREETYPE_DELEGATE)
 
+static size_t ShapeGlyph(const char *text,const ssize_t size,FT_Face face,
+  const raqm_direction_t direction,const double kerning,const FT_Int32 flags,
+  raqm_glyph_info_t **glyph_shape)
+{
+  FT_Error
+    ft_status;
+
+  register ssize_t
+    i;
+
+  ssize_t
+    last_glyph;
+
+  *glyph_shape=(raqm_glyph_info_t *) AcquireQuantumMemory(size+1,
+    sizeof(**glyph_shape));
+  if (*glyph_shape == (raqm_glyph_info_t *) NULL)
+    return(0);
+  last_glyph=0;
+  for (i=0; GetUTFCode(text) != 0; text+=GetUTFOctets(text), i++)
+  {
+    (*glyph_shape)[i].index=FT_Get_Char_Index(face,GetUTFCode(text));
+    (*glyph_shape)[i].x_offset=0;
+    (*glyph_shape)[i].y_offset=0;
+    if (((*glyph_shape)[i].index != 0) && (last_glyph != 0))
+      {
+        if (FT_HAS_KERNING(face))
+          {
+            FT_Vector
+              kerning_vector;
+
+            ft_status=FT_Get_Kerning(face,last_glyph,(*glyph_shape)[i].index,
+              ft_kerning_default,&kerning_vector);
+            if (ft_status == 0)
+              (*glyph_shape)[i].x_offset=(FT_Pos) ((direction ==
+                RAQM_DIRECTION_RTL ? -1.0 : 1.0)*kerning_vector.x);
+          }
+      (*glyph_shape)[i].x_offset=(FT_Pos) (64.0*(direction ==
+        RAQM_DIRECTION_RTL ? -1.0 : 1.0)*kerning);
+    }
+    ft_status=FT_Load_Glyph(face,(*glyph_shape)[i].index,flags);
+    (*glyph_shape)[i].x_advance=face->glyph->advance.x;
+    (*glyph_shape)[i].cluster=GetUTFCode(text);
+    last_glyph=(*glyph_shape)[i].index;
+  }
+  return((size_t) i);
+}
+
 static int TraceCubicBezier(FT_Vector *p,FT_Vector *q,FT_Vector *to,
   DrawInfo *draw_info)
 {
@@ -1086,9 +1155,6 @@ static MagickBooleanType RenderFreetype(Image *image,const DrawInfo *draw_info,
   const char
     *value;
 
-  double
-    direction;
-
   DrawInfo
     *annotate_info;
 
@@ -1133,9 +1199,21 @@ static MagickBooleanType RenderFreetype(Image *image,const DrawInfo *draw_info,
     point,
     resolution;
 
+  raqm_direction_t
+    direction;
+
+  raqm_glyph_info_t
+    *glyph_shape;
+
   register char
     *p;
 
+  register ssize_t
+    i;
+
+  size_t
+    length;
+
   ssize_t
     code,
     y;
@@ -1236,12 +1314,12 @@ static MagickBooleanType RenderFreetype(Image *image,const DrawInfo *draw_info,
         geometry_info;
 
       MagickStatusType
-        geometry_flags;
+        flags;
 
-      geometry_flags=ParseGeometry(draw_info->density,&geometry_info);
+      flags=ParseGeometry(draw_info->density,&geometry_info);
       resolution.x=geometry_info.rho;
       resolution.y=geometry_info.sigma;
-      if ((geometry_flags & SigmaValue) == 0)
+      if ((flags & SigmaValue) == 0)
         resolution.y=resolution.x;
     }
   ft_status=FT_Set_Char_Size(face,(FT_F26Dot6) (64.0*draw_info->pointsize),
@@ -1322,9 +1400,6 @@ static MagickBooleanType RenderFreetype(Image *image,const DrawInfo *draw_info,
       if (image->alpha_trait == UndefinedPixelTrait)
         (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
     }
-  direction=1.0;
-  if (draw_info->direction == RightToLeftDirection)
-    direction=(-1.0);
   point.x=0.0;
   point.y=0.0;
   for (p=draw_info->text; GetUTFCode(p) != 0; p+=GetUTFOctets(p))
@@ -1340,29 +1415,33 @@ static MagickBooleanType RenderFreetype(Image *image,const DrawInfo *draw_info,
         p=(char *) utf8;
     }
   status=MagickTrue;
-  for (code=0; GetUTFCode(p) != 0; p+=GetUTFOctets(p))
+  direction=RAQM_DIRECTION_DEFAULT;
+  if (draw_info->direction == RightToLeftDirection)
+    direction=RAQM_DIRECTION_RTL;
+  else
+    if (draw_info->direction == LeftToRightDirection)
+      direction=RAQM_DIRECTION_LTR;
+  glyph_shape=(raqm_glyph_info_t *) NULL;
+#if defined(MAGICKCORE_CTL_DELEGATE)
+  length=(size_t) raqm_shape(p,strlen(p),face,direction,&glyph_shape);
+#else
+  length=ShapeGlyph(p,strlen(p),face,direction,draw_info->kerning,flags,
+    &glyph_shape);
+#endif
+  code=0;
+  for (i=0; i < (ssize_t) length; i++)
   {
     /*
       Render UTF-8 sequence.
     */
-    glyph.id=FT_Get_Char_Index(face,GetUTFCode(p));
+    glyph.id=glyph_shape[i].index;
     if (glyph.id == 0)
       glyph.id=FT_Get_Char_Index(face,'?');
     if ((glyph.id != 0) && (last_glyph.id != 0))
-      {
-        if (FT_HAS_KERNING(face))
-          {
-            FT_Vector
-              kerning;
-
-            ft_status=FT_Get_Kerning(face,last_glyph.id,glyph.id,
-              ft_kerning_default,&kerning);
-            if (ft_status == 0)
-              origin.x+=(FT_Pos) (direction*kerning.x);
-          }
-        origin.x+=(FT_Pos) (64.0*direction*draw_info->kerning);
-      }
+      origin.x+=(FT_Pos) (64.0*draw_info->kerning);
     glyph.origin=origin;
+    glyph.origin.x+=glyph_shape[i].x_offset;
+    glyph.origin.y+=glyph_shape[i].y_offset;
     ft_status=FT_Load_Glyph(face,glyph.id,flags);
     if (ft_status != 0)
       continue;
@@ -1389,7 +1468,7 @@ static MagickBooleanType RenderFreetype(Image *image,const DrawInfo *draw_info,
           Trace the glyph.
         */
         annotate_info->affine.tx=glyph.origin.x/64.0;
-        annotate_info->affine.ty=glyph.origin.y/64.0;
+        annotate_info->affine.ty=(-glyph.origin.y/64.0);
         (void) FT_Outline_Decompose(&((FT_OutlineGlyph) glyph.image)->outline,
           &OutlineMethods,annotate_info);
       }
@@ -1515,18 +1594,20 @@ static MagickBooleanType RenderFreetype(Image *image,const DrawInfo *draw_info,
     if ((bitmap->left+bitmap->bitmap.width) > metrics->width)
       metrics->width=bitmap->left+bitmap->bitmap.width;
     if ((fabs(draw_info->interword_spacing) >= MagickEpsilon) &&
-        (IsUTFSpace(GetUTFCode(p)) != MagickFalse) &&
+        (IsUTFSpace(GetUTFCode(p+glyph_shape[i].cluster)) != MagickFalse) &&
         (IsUTFSpace(code) == MagickFalse))
-      origin.x+=(FT_Pos) (64.0*direction*draw_info->interword_spacing);
+      origin.x+=(FT_Pos) (64.0*draw_info->interword_spacing);
     else
-      origin.x+=(FT_Pos) (direction*face->glyph->advance.x);
+      origin.x+=(FT_Pos) glyph_shape[i].x_advance;
     metrics->origin.x=(double) origin.x;
     metrics->origin.y=(double) origin.y;
     if (last_glyph.id != 0)
       FT_Done_Glyph(last_glyph.image);
     last_glyph=glyph;
-    code=GetUTFCode(p);
+    code=GetUTFCode(p+glyph_shape[i].cluster);
   }
+  if (glyph_shape != (raqm_glyph_info_t *) NULL)
+    glyph_shape=(raqm_glyph_info_t *) RelinquishMagickMemory(glyph_shape);
   if (utf8 != (unsigned char *) NULL)
     utf8=(unsigned char *) RelinquishMagickMemory(utf8);
   if (last_glyph.id != 0)