Hello !
How can I write text directly on a painted bitmap ?
I am sending you my source code.

Regards, Łukasz Płuska

#pragma once

#include <math.h>


void draw_bitmap(FT_Bitmap* bitmap, int px, int py, unsigned int fontColor, 
                 unsigned int backgroundColor,
                         RGBQUAD *image,
                         int image_cx,
                         int image_cy )
{
    /* 
     Note that the coloured bitmap isn't cached, which means that the 
     transparency calculation is performed on a character bitmap every time
     a character is written to the video buffer. This isn't good if you are
     concerned with performance.
     */
    int x_max = bitmap->width;
    int y_max = bitmap->rows;
    int x, y;
    
    unsigned int fontColorR = ((fontColor & 0x00FF0000) >> 16);
    unsigned int fontColorG = ((fontColor & 0x0000FF00) >> 8);
    unsigned int fontColorB = (fontColor & 0x000000FF);
    
    unsigned int backgroundColorR = ((backgroundColor & 0x00FF0000) >> 16);
    unsigned int backgroundColorG = ((backgroundColor & 0x0000FF00) >> 8);
    unsigned int backgroundColorB = (backgroundColor & 0x000000FF);
        
    float opacity;
    
    for(x = 0; x < x_max; x++){        /* For each horizontal pixel..        */
        for(y = 0; y < y_max; y++){    /* ...in each row of the font bitmap. */
            
            if(x >= image_cx || y >= image_cy){ continue; }

                        backgroundColorR = image[( image_cy - py - y - 1 ) * 
image_cx + (px + x)].rgbRed;
                        backgroundColorG = image[( image_cy - py - y - 1 ) * 
image_cx + (px + x)].rgbGreen;
                        backgroundColorB = image[( image_cy - py - y - 1 ) * 
image_cx + (px + x)].rgbBlue;
            
            if(bitmap->buffer[y * bitmap->width + x] == 0){ 
                /* Render background color. */
                image[(py + y) * image_cx + (px + x)].rgbRed = 
backgroundColorR; 
                image[(py + y) * image_cx + (px + x)].rgbGreen = 
backgroundColorG;
                image[(py + y) * image_cx + (px + x)].rgbBlue = 
backgroundColorB;
            }else {
                /* Calculate alpha (opacity). */
                opacity = bitmap->buffer[y * bitmap->width + x] / 255.0;
                
                image[( image_cy - py - y - 1 ) * image_cx + (px + x)].rgbRed = 
fontColorR * opacity +
                (1 - opacity) * backgroundColorR;
                
                image[(image_cy - py - y - 1) * image_cx + (px + x)].rgbGreen = 
fontColorG * opacity +
                (1 - opacity) * backgroundColorG;
                
                image[(image_cy - py - y - 1) * image_cx + (px + x)].rgbBlue = 
fontColorB * opacity +
                (1 - opacity) * backgroundColorB;
            }                        
        }
    }
}


void
draw_bitmap( FT_Bitmap*  bitmap,
             FT_Int      x,
             FT_Int      y,
                         RGBQUAD *image,
                         int image_cx,
                         int image_cy, 
                         DRGBQUAD *TextColor )
{
  FT_Int  i, j, p, q;
  FT_Int  x_max = x + bitmap->width;
  FT_Int  y_max = y + bitmap->rows;


  /* for simplicity, we assume that `bitmap->pixel_mode' */
  /* is `FT_PIXEL_MODE_GRAY' (i.e., not a bitmap font)   */

                /*

                DWORD value;

                if ( ImgIn->rgbRed == 0xFF ) {
                        ImgOut->rgbRed = TextColor->rgbRed;
                } else if ( ImgIn->rgbBlue == 0x00 ) {
                        ImgOut->rgbRed = ImgOut->rgbRed;
                } else {
                        value = ( (DWORD)TextColor->rgbRed * ( 
(DWORD)ImgIn->rgbRed ) / 255 )
                                + ( (DWORD)ImgOut->rgbRed * ( 255 - 
(DWORD)ImgIn->rgbRed ) / 255 ) ;
                        if ( value > 255 ) value = 255;
                        ImgOut->rgbRed = value;
                }*/

  for ( i = x, p = 0; i < x_max; i++, p++ )
  {
    for ( j = y, q = 0; j < y_max; j++, q++ )
    {
      if ( i < 0      || j < 0       ||
           i >= image_cx || j >= image_cy )
        continue;

                double value;

                BYTE src = bitmap->buffer[q * bitmap->width + p];
                BYTE dest = (image_cy-j-1)*image_cx+i;

                if ( src == 0xFF ) {
                        value = (double)( TextColor->Red * 255.0f );
                } else if ( src == 0x00 ) {
                        value = image[(image_cy-j-1)*image_cx+i].rgbRed;
                } else {
                        value = ( TextColor->Red * ( (double)src ) ) + ( 
(double)(image[dest].rgbRed) * ( 255 - (double)src ) / 255 ) ;
                }
                        
                if ( value > 255 ) value = 255;
                image[(image_cy-j-1)*image_cx+i].rgbRed = value;

                

                if ( src == 0xFF ) {
                        value = (double)( TextColor->Green * 255.0f );
                } else if ( src == 0x00 ) {
                        value = image[(image_cy-j-1)*image_cx+i].rgbGreen;
                } else {
                        value = ( TextColor->Green * ( (double)src ) ) + ( 
(double)(image[dest].rgbGreen) * ( 255 - (double)src ) / 255 ) ;
                }
                        
                if ( value > 255 ) value = 255;
                image[(image_cy-j-1)*image_cx+i].rgbGreen = value;

                

                if ( src == 0xFF ) {
                        value = (double)( TextColor->Blue * 255.0f );
                } else if ( src == 0x00 ) {
                        value = image[(image_cy-j-1)*image_cx+i].rgbBlue;
                } else {
                        value = ( TextColor->Blue * ( (double)src ) ) + ( 
(double)(image[dest].rgbBlue) * ( 255 - (double)src ) / 255 ) ;
                }
                        
                if ( value > 255 ) value = 255;
                image[(image_cy-j-1)*image_cx+i].rgbBlue = value;



                //continue;

                /*if ( src == 0xFF ) {
                        image[dest].rgbGreen = TextColor.Green * 255.0f;
                } else if ( src == 0x00 ) {
                        //image[dest].rgbGreen = ImgOut->rgbGreen;
                } else {
                        value = ( TextColor.Green * ( (double)src ) )
                                + ( (DWORD)(image[dest].rgbGreen) * ( 255 - 
(DWORD)src ) / 255 ) ;
                        if ( value > 255 ) value = 255;
                        image[dest].rgbGreen = value;
                }

                if ( src == 0xFF ) {
                        image[dest].rgbBlue = TextColor.Blue * 255.0f;
                } else if ( src == 0x00 ) {
                        //image[dest].rgbBlue = ImgOut->rgbBlue;
                } else {
                        value = ( TextColor.Blue * ( (double)src ) )
                                + ( (DWORD)(image[dest].rgbBlue) * ( 255 - 
(DWORD)src ) / 255 ) ;
                        if ( value > 255 ) value = 255;
                        image[dest].rgbBlue = value;
                }*/

      //image[(image_cy-j-1)*image_cx+i].rgbRed = bitmap->buffer[q * 
bitmap->width + p];
     //image[(image_cy-j-1)*image_cx+i].rgbGreen =bitmap->buffer[q * 
bitmap->width + p];
      //image[(image_cy-j-1)*image_cx+i].rgbBlue = bitmap->buffer[q * 
bitmap->width + p];
    }
  }
}

bool PDF_DrawText( PDF_FILE *pdf, FT_Library library, WCHAR *text, double x, 
double y, char *FontName,
                                  FT_UInt  pixel_width, FT_UInt  pixel_height, 
DRGBQUAD *TextColor, BYTE RenderingMode, double angle = 0 ) {

        long n;

        for ( n = 0; n < PDF_GLOBAL_FONT_NR; n++ ) {
                if ( lstrcmpiA( FontName, g_Fonts[n].FontName ) == 0 ) break;
        }

        if ( n >= PDF_GLOBAL_FONT_NR ) {
                return false;
        }

        FT_Face     face;

        ZeroMemory( pdf->Page.HelpImage, pdf->Page.Width * pdf->Page.Height * 
sizeof(RGBQUAD) );

        FT_Error error = FT_New_Memory_Face( library,
                g_Fonts[n].Data,    // first byte in memory 
                g_Fonts[n].DataLenght,      // size in bytes        
                0,         // face_index           
                &face );

        //FT_Bitmap

        if ( error == 0 ) {

                //error = FT_Set_Pixel_Sizes( face, pixel_width, pixel_height 
);   // pixel_height

                FT_Stroker stroker;
                FT_Stroker_New(library, &stroker);
                //  2 * 64 result in 2px outline
                FT_Stroker_Set(stroker, 2 * 64, FT_STROKER_LINECAP_ROUND, 
FT_STROKER_LINEJOIN_ROUND, 0);

                error = FT_Set_Char_Size(
          face,    /* handle to face object           */
          pixel_width*64.0f,       /* char_width in 1/64th of points  */
          pixel_height*64.0f,   /* char_height in 1/64th of points */
          72,     /* horizontal device resolution    */
          72 );   /* vertical device resolution      */

                WCHAR *example_text = text;

                int example_text_len = wcslen( example_text );

                int n,dest_x = 0;

                FT_Vector     pen;
                FT_Matrix     matrix;

                FT_GlyphSlot  slot;

                slot = face->glyph;

                //double angle         = 0;//( 25.0 / 360 ) * 3.14159 * 2;      
// use 25 degrees    
                int target_height = pdf->Page.Height;

                matrix.xx = (FT_Fixed)( cos( angle ) * 0x10000L );
                matrix.xy = (FT_Fixed)(-sin( angle ) * 0x10000L );
                matrix.yx = (FT_Fixed)( sin( angle ) * 0x10000L );
                matrix.yy = (FT_Fixed)( cos( angle ) * 0x10000L );

                        FT_Set_Transform( face, &matrix, &pen );

                pen.x = (FT_Pos)( x * 64.0f );
                //pen.y = ( pdf->Page.Height - y ) * 64;
                pen.y = (FT_Pos)( y * 64.0f );

                //FT_GlyphSlot  slot = face->glyph;

                //int target_height = pdf->Page.Height;

                for ( n = 0; n < example_text_len; n++ ) {      

                        /*FT_UInt glyphIndex = FT_Get_Char_Index(face, 
example_text[n]);
                        FT_Load_Glyph(face, glyphIndex, FT_LOAD_DEFAULT);
                        FT_Glyph glyph;
                        FT_Get_Glyph(face->glyph, &glyph);
                        FT_Glyph_StrokeBorder(&glyph, stroker, false, true);
                        FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 
true);

                        draw_bitmap( &slot->bitmap, slot->bitmap_left, 
target_height - slot->bitmap_top, 
                                pdf->Page.Image, pdf->Page.Width, 
pdf->Page.Height, &TextColor[n] );*/


                        //face->

                        FT_Set_Transform( face, &matrix, &pen );

                        //error = FT_Load_Glyph( face, example_text[n], 
FT_LOAD_RENDER );

                        error = FT_Load_Char( face, example_text[n], 
FT_LOAD_RENDER );

                        if ( error ) continue;

                        FT_Glyph glyph;
                        FT_Get_Glyph(face->glyph, &glyph);

                        FT_Glyph_StrokeBorder(&glyph, stroker, false, true);

                        draw_bitmap( &slot->bitmap, slot->bitmap_left, 
target_height - slot->bitmap_top, 
                                pdf->Page.Image, pdf->Page.Width, 
pdf->Page.Height, &TextColor[n] );

                        //draw_bitmap( &slot->bitmap, slot->bitmap_left, 
target_height - slot->bitmap_top, 0x000000, 0xFFFFFF,
                        //      pdf->Page.Image, pdf->Page.Width, 
pdf->Page.Height );


                        //sprintf( szBuffer, "%u %u %u\n%u %u %u", 
slot->bitmap.width, slot->bitmap.rows, slot->bitmap.pitch, 
                        //      slot->bitmap.num_grays, 
slot->bitmap.pixel_mode, slot->bitmap.palette_mode );

                        //MessageBoxA( 0, szBuffer, "slot->bitmap", 0);

                        //draw_bitmap( &slot->bitmap, slot->bitmap_left, 
target_height - slot->bitmap_top, 
                        //      pdf->Page.HelpImage, pdf->Page.Width, 
pdf->Page.Height );

                        pen.x += slot->advance.x;
                        pen.y += slot->advance.y;

                        /*FT_UInt  glyph_index;

                        // retrieve glyph index from character code 
                        glyph_index = FT_Get_Char_Index( face, text[n] );

                        // load glyph image into the slot (erase previous one) 
                        error = FT_Load_Glyph( face, glyph_index, 
FT_LOAD_DEFAULT );
                        if ( error )
                          continue;  // ignore errors 

                        // convert to an anti-aliased bitmap 
                        error = FT_Render_Glyph( face->glyph, 
FT_RENDER_MODE_NORMAL );
                        if ( error )
                          continue;

                        // now, draw to our target surface 
                        draw_bitmap( &slot->bitmap,
                                                        pen.x + 
slot->bitmap_left,
                                                        pen.y - 
slot->bitmap_top, pdf->Page.HelpImage, pdf->Page.Width, pdf->Page.Height, 
&TextColor[n]  );

                        // increment pen position 
                        pen.x += slot->advance.x >> 6;
                        pen.y += slot->advance.y >> 6; // not useful for now */


                }

                return true;
        }


        return false;
}


void PDF_CopyText( RGBQUAD *out, RGBQUAD *in, DWORD cx, DWORD cy, RGBQUAD 
*TextColor ) {

        RGBQUAD *ImgIn = in;
        RGBQUAD *ImgInMax = &in[ cx * cy ];
        RGBQUAD *ImgOut = out;

        while ( ImgIn < ImgInMax ) {

                DWORD value;

                if ( ImgIn->rgbRed == 0xFF ) {
                        ImgOut->rgbRed = TextColor->rgbRed;
                } else if ( ImgIn->rgbBlue == 0x00 ) {
                        ImgOut->rgbRed = ImgOut->rgbRed;
                } else {
                        value = ( (DWORD)TextColor->rgbRed * ( 
(DWORD)ImgIn->rgbRed ) / 255 )
                                + ( (DWORD)ImgOut->rgbRed * ( 255 - 
(DWORD)ImgIn->rgbRed ) / 255 ) ;
                        if ( value > 255 ) value = 255;
                        ImgOut->rgbRed = value;
                }

                if ( ImgIn->rgbGreen == 0xFF ) {
                        ImgOut->rgbGreen = TextColor->rgbGreen;
                } else if ( ImgIn->rgbGreen == 0x00 ) {
                        ImgOut->rgbGreen = ImgOut->rgbGreen;
                } else {
                        value = ( (DWORD)TextColor->rgbGreen * ( 
(DWORD)ImgIn->rgbGreen ) / 255 )
                                + ( (DWORD)ImgOut->rgbGreen * ( 255 - 
(DWORD)ImgIn->rgbGreen ) / 255 ) ;
                        if ( value > 255 ) value = 255;
                        ImgOut->rgbGreen = value;
                }

                if ( ImgIn->rgbBlue == 0xFF ) {
                        ImgOut->rgbBlue = TextColor->rgbBlue;
                } else if ( ImgIn->rgbBlue == 0x00 ) {
                        ImgOut->rgbBlue = ImgOut->rgbBlue;
                } else {
                        value = ( (DWORD)TextColor->rgbBlue * ( 
(DWORD)ImgIn->rgbBlue ) / 255 )
                                + ( (DWORD)ImgOut->rgbBlue * ( 255 - 
(DWORD)ImgIn->rgbBlue ) / 255 ) ;
                        if ( value > 255 ) value = 255;
                        ImgOut->rgbBlue = value;
                }

                ImgIn++;
                ImgOut++;

        }
}
_______________________________________________
Freetype-devel mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/freetype-devel

Reply via email to