Commit 6de761744cad81c3ab53db0b77fb56c69cdfbac7

Werner Lemberg 2014-11-21T06:05:49

* src/base/ftbitmap.c (FT_Bitmap_Copy): Improve. This commit adds argument checks and support for different flow directions.

diff --git a/ChangeLog b/ChangeLog
index 65e5c16..c62b5f5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2014-11-21  Werner Lemberg  <wl@gnu.org>
+
+	* src/base/ftbitmap.c (FT_Bitmap_Copy): Improve.
+
+	This commit adds argument checks and support for different flow
+	directions.
+
 2014-11-20  Werner Lemberg  <wl@gnu.org>
 
 	* src/base/ftbitmap.c (FT_Bitmap_New): Check argument.
diff --git a/src/base/ftbitmap.c b/src/base/ftbitmap.c
index d333643..b33afec 100644
--- a/src/base/ftbitmap.c
+++ b/src/base/ftbitmap.c
@@ -45,22 +45,39 @@
                   const FT_Bitmap  *source,
                   FT_Bitmap        *target)
   {
-    FT_Memory  memory = library->memory;
+    FT_Memory  memory;
     FT_Error   error  = FT_Err_Ok;
-    FT_Int     pitch  = source->pitch;
-    FT_ULong   size;
 
+    FT_Int    pitch;
+    FT_ULong  size;
+
+    FT_Int  source_pitch_sign, target_pitch_sign;
+
+
+    if ( !library )
+      return FT_THROW( Invalid_Library_Handle );
+
+    if ( !source || !target )
+      return FT_THROW( Invalid_Argument );
 
     if ( source == target )
       return FT_Err_Ok;
 
+    source_pitch_sign = source->pitch < 0 ? -1 : 1;
+    target_pitch_sign = target->pitch < 0 ? -1 : 1;
+
     if ( source->buffer == NULL )
     {
       *target = *source;
+      if ( source_pitch_sign != target_pitch_sign )
+        target->pitch = -target->pitch;
 
       return FT_Err_Ok;
     }
 
+    memory = library->memory;
+    pitch  = source->pitch;
+
     if ( pitch < 0 )
       pitch = -pitch;
     size = (FT_ULong)pitch * source->rows;
@@ -71,7 +88,7 @@
       FT_ULong  target_size;
 
 
-      if ( target_pitch < 0  )
+      if ( target_pitch < 0 )
         target_pitch = -target_pitch;
       target_size = (FT_ULong)target_pitch * target->rows;
 
@@ -90,7 +107,26 @@
       *target = *source;
       target->buffer = p;
 
-      FT_MEM_COPY( target->buffer, source->buffer, size );
+      if ( source_pitch_sign == target_pitch_sign )
+        FT_MEM_COPY( target->buffer, source->buffer, size );
+      else
+      {
+        /* take care of bitmap flow */
+        FT_UInt   i;
+        FT_Byte*  s = source->buffer;
+        FT_Byte*  t = target->buffer;
+
+
+        t += pitch * ( target->rows - 1 );
+
+        for ( i = target->rows; i > 0; i-- )
+        {
+          FT_ARRAY_COPY( t, s, pitch );
+
+          s += pitch;
+          t -= pitch;
+        }
+      }
     }
 
     return error;