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