< prev index next >

src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c

Print this page

        

@@ -1,33 +1,43 @@
-/***************************************************************************/
-/*                                                                         */
-/*  ftbitmap.c                                                             */
-/*                                                                         */
-/*    FreeType utility functions for bitmaps (body).                       */
-/*                                                                         */
-/*  Copyright 2004-2018 by                                                 */
-/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
-/*                                                                         */
-/*  This file is part of the FreeType project, and may only be used,       */
-/*  modified, and distributed under the terms of the FreeType project      */
-/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
-/*  this file you indicate that you have read the license and              */
-/*  understand and accept it fully.                                        */
-/*                                                                         */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftbitmap.c
+ *
+ *   FreeType utility functions for bitmaps (body).
+ *
+ * Copyright (C) 2004-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
 
 
 #include <ft2build.h>
 #include FT_INTERNAL_DEBUG_H
 
 #include FT_BITMAP_H
 #include FT_IMAGE_H
 #include FT_INTERNAL_OBJECTS_H
 
 
+  /**************************************************************************
+   *
+   * The macro FT_COMPONENT is used in trace mode.  It is an implicit
+   * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+   * messages during execution.
+   */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  bitmap
+
+
   static
-  const FT_Bitmap  null_bitmap = { 0, 0, 0, 0, 0, 0, 0, 0 };
+  const FT_Bitmap  null_bitmap = { 0, 0, 0, NULL, 0, 0, 0, NULL };
 
 
   /* documentation is in ftbitmap.h */
 
   FT_EXPORT_DEF( void )

@@ -781,10 +791,335 @@
 
     return error;
   }
 
 
+  /* documentation is in ftbitmap.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Bitmap_Blend( FT_Library        library,
+                   const FT_Bitmap*  source_,
+                   const FT_Vector   source_offset_,
+                   FT_Bitmap*        target,
+                   FT_Vector        *atarget_offset,
+                   FT_Color          color )
+  {
+    FT_Error   error = FT_Err_Ok;
+    FT_Memory  memory;
+
+    FT_Bitmap         source_bitmap;
+    const FT_Bitmap*  source;
+
+    FT_Vector  source_offset;
+    FT_Vector  target_offset;
+
+    FT_Bool  free_source_bitmap          = 0;
+    FT_Bool  free_target_bitmap_on_error = 0;
+
+    FT_Pos  source_llx, source_lly, source_urx, source_ury;
+    FT_Pos  target_llx, target_lly, target_urx, target_ury;
+    FT_Pos  final_llx, final_lly, final_urx, final_ury;
+
+    unsigned int  final_rows, final_width;
+    long          x, y;
+
+
+    if ( !library || !target || !source_ || !atarget_offset )
+      return FT_THROW( Invalid_Argument );
+
+    memory = library->memory;
+
+    if ( !( target->pixel_mode == FT_PIXEL_MODE_NONE     ||
+            ( target->pixel_mode == FT_PIXEL_MODE_BGRA &&
+              target->buffer                           ) ) )
+      return FT_THROW( Invalid_Argument );
+
+    if ( source_->pixel_mode == FT_PIXEL_MODE_NONE )
+      return FT_Err_Ok;               /* nothing to do */
+
+    /* pitches must have the same sign */
+    if ( target->pixel_mode == FT_PIXEL_MODE_BGRA &&
+         ( source_->pitch ^ target->pitch ) < 0   )
+      return FT_THROW( Invalid_Argument );
+
+    if ( !( source_->width && source_->rows ) )
+      return FT_Err_Ok;               /* nothing to do */
+
+    /* assure integer pixel offsets */
+    source_offset.x = FT_PIX_FLOOR( source_offset_.x );
+    source_offset.y = FT_PIX_FLOOR( source_offset_.y );
+    target_offset.x = FT_PIX_FLOOR( atarget_offset->x );
+    target_offset.y = FT_PIX_FLOOR( atarget_offset->y );
+
+    /* get source bitmap dimensions */
+    source_llx = source_offset.x;
+    if ( FT_LONG_MIN + (FT_Pos)( source_->rows << 6 ) + 64 > source_offset.y )
+    {
+      FT_TRACE5((
+        "FT_Bitmap_Blend: y coordinate overflow in source bitmap\n" ));
+      return FT_THROW( Invalid_Argument );
+    }
+    source_lly = source_offset.y - ( source_->rows << 6 );
+
+    if ( FT_LONG_MAX - (FT_Pos)( source_->width << 6 ) - 64 < source_llx )
+    {
+      FT_TRACE5((
+        "FT_Bitmap_Blend: x coordinate overflow in source bitmap\n" ));
+      return FT_THROW( Invalid_Argument );
+    }
+    source_urx = source_llx + ( source_->width << 6 );
+    source_ury = source_offset.y;
+
+    /* get target bitmap dimensions */
+    if ( target->width && target->rows )
+    {
+      target_llx = target_offset.x;
+      if ( FT_LONG_MIN + (FT_Pos)( target->rows << 6 ) > target_offset.y )
+      {
+        FT_TRACE5((
+          "FT_Bitmap_Blend: y coordinate overflow in target bitmap\n" ));
+        return FT_THROW( Invalid_Argument );
+      }
+      target_lly = target_offset.y - ( target->rows << 6 );
+
+      if ( FT_LONG_MAX - (FT_Pos)( target->width << 6 ) < target_llx )
+      {
+        FT_TRACE5((
+          "FT_Bitmap_Blend: x coordinate overflow in target bitmap\n" ));
+        return FT_THROW( Invalid_Argument );
+      }
+      target_urx = target_llx + ( target->width << 6 );
+      target_ury = target_offset.y;
+    }
+    else
+    {
+      target_llx = FT_LONG_MAX;
+      target_lly = FT_LONG_MAX;
+      target_urx = FT_LONG_MIN;
+      target_ury = FT_LONG_MIN;
+    }
+
+    /* compute final bitmap dimensions */
+    final_llx = FT_MIN( source_llx, target_llx );
+    final_lly = FT_MIN( source_lly, target_lly );
+    final_urx = FT_MAX( source_urx, target_urx );
+    final_ury = FT_MAX( source_ury, target_ury );
+
+    final_width = ( final_urx - final_llx ) >> 6;
+    final_rows  = ( final_ury - final_lly ) >> 6;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+    FT_TRACE5(( "FT_Bitmap_Blend:\n"
+                "  source bitmap: (%d, %d) -- (%d, %d); %d x %d\n",
+      source_llx / 64, source_lly / 64,
+      source_urx / 64, source_ury / 64,
+      source_->width, source_->rows ));
+
+    if ( target->width && target->rows )
+      FT_TRACE5(( "  target bitmap: (%d, %d) -- (%d, %d); %d x %d\n",
+        target_llx / 64, target_lly / 64,
+        target_urx / 64, target_ury / 64,
+        target->width, target->rows ));
+    else
+      FT_TRACE5(( "  target bitmap: empty\n" ));
+
+    FT_TRACE5(( "  final bitmap: (%d, %d) -- (%d, %d); %d x %d\n",
+      final_llx / 64, final_lly / 64,
+      final_urx / 64, final_ury / 64,
+      final_width, final_rows ));
+#endif /* FT_DEBUG_LEVEL_TRACE */
+
+    /* for blending, set offset vector of final bitmap */
+    /* temporarily to (0,0)                            */
+    source_llx -= final_llx;
+    source_lly -= final_lly;
+
+    if ( target->width && target->rows )
+    {
+      target_llx -= final_llx;
+      target_lly -= final_lly;
+    }
+
+    /* set up target bitmap */
+    if ( target->pixel_mode == FT_PIXEL_MODE_NONE )
+    {
+      /* create new empty bitmap */
+      target->width      = final_width;
+      target->rows       = final_rows;
+      target->pixel_mode = FT_PIXEL_MODE_BGRA;
+      target->pitch      = (int)final_width * 4;
+      target->num_grays  = 256;
+
+      if ( FT_LONG_MAX / target->pitch < (int)target->rows )
+      {
+        FT_TRACE5(( "FT_Blend_Bitmap: target bitmap too large (%d x %d)\n",
+                     final_width, final_rows ));
+        return FT_THROW( Invalid_Argument );
+      }
+
+      if ( FT_ALLOC( target->buffer, target->pitch * (int)target->rows ) )
+        return error;
+
+      free_target_bitmap_on_error = 1;
+    }
+    else if ( target->width != final_width ||
+              target->rows  != final_rows  )
+    {
+      /* adjust old bitmap to enlarged size */
+      int  pitch, new_pitch;
+
+      unsigned char*  buffer = NULL;
+
+
+      pitch = target->pitch;
+      if ( pitch < 0 )
+        pitch = -pitch;
+
+      new_pitch = (int)final_width * 4;
+
+      if ( FT_LONG_MAX / new_pitch < (int)final_rows )
+      {
+        FT_TRACE5(( "FT_Blend_Bitmap: target bitmap too large (%d x %d)\n",
+                     final_width, final_rows ));
+        return FT_THROW( Invalid_Argument );
+      }
+
+      /* TODO: provide an in-buffer solution for large bitmaps */
+      /*       to avoid allocation of a new buffer             */
+      if ( FT_ALLOC( buffer, new_pitch * (int)final_rows ) )
+        goto Error;
+
+      /* copy data to new buffer */
+      x = target_llx >> 6;
+      y = target_lly >> 6;
+
+      /* the bitmap flow is from top to bottom, */
+      /* but y is measured from bottom to top   */
+      if ( target->pitch < 0 )
+      {
+        /* XXX */
+      }
+      else
+      {
+        unsigned char*  p =
+          target->buffer;
+        unsigned char*  q =
+          buffer +
+          ( final_rows - y - target->rows ) * new_pitch +
+          x * 4;
+        unsigned char*  limit_p =
+          p + pitch * (int)target->rows;
+
+
+        while ( p < limit_p )
+        {
+          FT_MEM_COPY( q, p, pitch );
+
+          p += pitch;
+          q += new_pitch;
+        }
+      }
+
+      FT_FREE( target->buffer );
+
+      target->width = final_width;
+      target->rows  = final_rows;
+
+      if ( target->pitch < 0 )
+        target->pitch = -new_pitch;
+      else
+        target->pitch = new_pitch;
+
+      target->buffer = buffer;
+    }
+
+    /* adjust source bitmap if necessary */
+    if ( source_->pixel_mode != FT_PIXEL_MODE_GRAY )
+    {
+      FT_Bitmap_Init( &source_bitmap );
+      error = FT_Bitmap_Convert( library, source_, &source_bitmap, 1 );
+      if ( error )
+        goto Error;
+
+      source             = &source_bitmap;
+      free_source_bitmap = 1;
+    }
+    else
+      source = source_;
+
+    /* do blending; the code below returns pre-multiplied channels, */
+    /* similar to what FreeType gets from `CBDT' tables             */
+    x = source_llx >> 6;
+    y = source_lly >> 6;
+
+    /* the bitmap flow is from top to bottom, */
+    /* but y is measured from bottom to top   */
+    if ( target->pitch < 0 )
+    {
+      /* XXX */
+    }
+    else
+    {
+      unsigned char*  p =
+        source->buffer;
+      unsigned char*  q =
+        target->buffer +
+        ( target->rows - y - source->rows ) * target->pitch +
+        x * 4;
+      unsigned char*  limit_p =
+        p + source->pitch * (int)source->rows;
+
+
+      while ( p < limit_p )
+      {
+        unsigned char*  r       = p;
+        unsigned char*  s       = q;
+        unsigned char*  limit_r = r + source->width;
+
+
+        while ( r < limit_r )
+        {
+          int  aa = *r++;
+          int  fa = color.alpha * aa / 255;
+
+          int  fb = color.blue * fa / 255;
+          int  fg = color.green * fa / 255;
+          int  fr = color.red * fa / 255;
+
+          int  ba2 = 255 - fa;
+
+          int  bb = s[0];
+          int  bg = s[1];
+          int  br = s[2];
+          int  ba = s[3];
+
+
+          *s++ = (unsigned char)( bb * ba2 / 255 + fb );
+          *s++ = (unsigned char)( bg * ba2 / 255 + fg );
+          *s++ = (unsigned char)( br * ba2 / 255 + fr );
+          *s++ = (unsigned char)( ba * ba2 / 255 + fa );
+        }
+
+        p += source->pitch;
+        q += target->pitch;
+      }
+    }
+
+    atarget_offset->x = final_llx;
+    atarget_offset->y = final_lly + ( final_rows << 6 );
+
+  Error:
+    if ( error && free_target_bitmap_on_error )
+      FT_Bitmap_Done( library, target );
+
+    if ( free_source_bitmap )
+      FT_Bitmap_Done( library, &source_bitmap );
+
+    return error;
+  }
+
+
   /* documentation is in ftbitmap.h */
 
   FT_EXPORT_DEF( FT_Error )
   FT_GlyphSlot_Own_Bitmap( FT_GlyphSlot  slot )
   {
< prev index next >