int LcdFont::getRenderWidth(const char * text, const bool utf8_encoded) { pthread_mutex_lock(&renderer->render_mutex); // fribidi #if defined (ENABLE_FRIBIDI) std::string Text = fribidiShapeChar(text, utf8_encoded); text = Text.c_str(); #endif FT_Error err; #ifdef FT_NEW_CACHE_API FTC_ScalerRec scaler; scaler.face_id = font.face_id; scaler.width = font.width; scaler.height = font.height; scaler.pixel = true; err = FTC_Manager_LookupSize(renderer->cacheManager, &scaler, &size); #else err = FTC_Manager_Lookup_Size(renderer->cacheManager, &font.font, &face, &size); #endif if (err != 0) { dprintf(DEBUG_NORMAL, "LcdFont::getRenderWidth: FTC_Manager_Lookup_Size failed! (0x%x)\n", err); pthread_mutex_unlock(&renderer->render_mutex); return -1; } int x=0; for (; *text; text++) { FTC_SBit glyph; int unicode_value = UTF8ToUnicode(text, utf8_encoded); if (unicode_value == -1) break; #ifdef FT_NEW_CACHE_API int index = FT_Get_Char_Index(size->face, unicode_value); #else int index=FT_Get_Char_Index(face, unicode_value); #endif if (!index) continue; if (getGlyphBitmap(index, &glyph)) { dprintf(DEBUG_NORMAL, "LcdFont::getRenderWidth: failed to get glyph bitmap.\n"); continue; } x+=glyph->xadvance+1; } pthread_mutex_unlock(&renderer->render_mutex); return x; }
ftc_image_node_init( FTC_ImageNode inode, FTC_GlyphQuery gquery, FTC_Cache cache ) { FTC_ImageFamily ifam = FTC_IMAGE_FAMILY( gquery->query.family ); FT_Error error; FT_Face face; FT_Size size; /* initialize its inner fields */ ftc_glyph_node_init( FTC_GLYPH_NODE( inode ), gquery->gindex, FTC_GLYPH_FAMILY( ifam ) ); /* we will now load the glyph image */ error = FTC_Manager_Lookup_Size( FTC_FAMILY( ifam )->cache->manager, &ifam->type.font, &face, &size ); if ( !error ) { FT_UInt gindex = FTC_GLYPH_NODE_GINDEX( inode ); error = FT_Load_Glyph( face, gindex, ifam->type.flags ); if ( !error ) { if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP || face->glyph->format == FT_GLYPH_FORMAT_OUTLINE ) { /* ok, copy it */ FT_Glyph glyph; error = FT_Get_Glyph( face->glyph, &glyph ); if ( !error ) { inode->glyph = glyph; goto Exit; } } else error = FTC_Err_Invalid_Argument; } } /* in case of error */ ftc_glyph_node_done( FTC_GLYPH_NODE(inode), cache ); Exit: return error; }
FT_CALLBACK_DEF FT_Error ftc_glyph_image_node_new( FTC_GlyphSet gset, FT_UInt glyph_index, FTC_GlyphImage *anode ) { FT_Memory memory = gset->memory; FTC_ImageSet imageset = (FTC_ImageSet)gset; FT_Error error; FTC_GlyphImage node = 0; FT_Face face; FT_Size size; /* allocate node */ if ( ALLOC( node, sizeof ( *node ) ) ) goto Exit; /* initialize its inner fields */ FTC_GlyphNode_Init( FTC_GLYPHNODE( node ), gset, glyph_index ); /* we will now load the glyph image */ error = FTC_Manager_Lookup_Size( gset->manager, &imageset->description.font, &face, &size ); if ( !error ) { FT_UInt gindex = node->root.glyph_index; FT_UInt load_flags = FT_LOAD_DEFAULT; FT_UInt image_type = imageset->description.image_type; if ( FTC_IMAGE_FORMAT( image_type ) == ftc_image_format_bitmap ) { load_flags |= FT_LOAD_RENDER; if ( image_type & ftc_image_flag_monochrome ) load_flags |= FT_LOAD_MONOCHROME; /* disable embedded bitmaps loading if necessary */ if ( image_type & ftc_image_flag_no_sbits ) load_flags |= FT_LOAD_NO_BITMAP; } else if ( FTC_IMAGE_FORMAT( image_type ) == ftc_image_format_outline ) { /* disable embedded bitmaps loading */ load_flags |= FT_LOAD_NO_BITMAP; if ( image_type & ftc_image_flag_unscaled ) load_flags |= FT_LOAD_NO_SCALE; } if ( image_type & ftc_image_flag_unhinted ) load_flags |= FT_LOAD_NO_HINTING; if ( image_type & ftc_image_flag_autohinted ) load_flags |= FT_LOAD_FORCE_AUTOHINT; error = FT_Load_Glyph( face, gindex, load_flags ); if ( !error ) { if ( face->glyph->format == ft_glyph_format_bitmap || face->glyph->format == ft_glyph_format_outline ) { /* ok, copy it */ FT_Glyph glyph; error = FT_Get_Glyph( face->glyph, &glyph ); if ( !error ) node->ft_glyph = glyph; } else error = FT_Err_Invalid_Argument; } } Exit: if ( error && node ) FREE( node ); *anode = node; return error; }
void LcdFont::RenderString(int x, int y, const int width, const char * text, const int color, const int selected, const bool utf8_encoded) { int err; pthread_mutex_lock(&renderer->render_mutex); #ifdef FT_NEW_CACHE_API FTC_ScalerRec scaler; scaler.face_id = font.face_id; scaler.width = font.width; scaler.height = font.height; scaler.pixel = true; if ((err = FTC_Manager_LookupSize(renderer->cacheManager, &scaler, &size)) != 0) #else if ((err=FTC_Manager_Lookup_Size(renderer->cacheManager, &font.font, &face, &size))!=0) #endif { printf("FTC_Manager_Lookup_Size failed! (%d)\n",err); pthread_mutex_unlock(&renderer->render_mutex); return; } int left=x, step_y=(size->metrics.height >> 6 )*3/4 + 4; int pos =0; for (; *text; text++) { pos++; FTC_SBit glyph; //if ((x + size->metrics.x_ppem > (left+width)) || (*text=='\n')) if (x + size->metrics.x_ppem > (left+width)) { //width clip break; } if (*text=='\n') { x = left; y += step_y; } int unicode_value = UTF8ToUnicode(text, utf8_encoded); if (unicode_value == -1) break; #ifdef FT_NEW_CACHE_API int index = FT_Get_Char_Index(size->face, unicode_value); #else int index = FT_Get_Char_Index(face, unicode_value); #endif if (!index) continue; if (getGlyphBitmap(index, &glyph)) { printf("failed to get glyph bitmap.\n"); continue; } int rx=x+glyph->left; int ry=y-glyph->top; if(pos==selected) { framebuffer->draw_fill_rect(x-2,y-glyph->height-2, x+glyph->width+2, y+2, CLCDDisplay::PIXEL_INV ); } for (int ay=0; ay<glyph->height; ay++) { int ax=0; int w=glyph->width; int xpos = rx; for (; ax<w; ax++) { unsigned char c = glyph->buffer[ay*abs(glyph->pitch)+(ax>>3)]; if((c>>(7-(ax&7)))&1) framebuffer->draw_point(xpos,ry, color); xpos ++; } ry++; } x+=glyph->xadvance+1; } pthread_mutex_unlock(&renderer->render_mutex); }
static FT_Error ftc_sbit_node_load( FTC_SBitNode snode, FTC_Manager manager, FTC_SBitFamily sfam, FT_UInt gindex, FT_ULong *asize ) { FT_Error error; FTC_GlyphNode gnode = FTC_GLYPH_NODE( snode ); FT_Memory memory; FT_Face face; FT_Size size; FTC_SBit sbit; if ( gindex < (FT_UInt)gnode->item_start || gindex >= (FT_UInt)gnode->item_start + gnode->item_count ) { FT_ERROR(( "ftc_sbit_node_load: invalid glyph index" )); return FTC_Err_Invalid_Argument; } memory = manager->library->memory; sbit = snode->sbits + ( gindex - gnode->item_start ); error = FTC_Manager_Lookup_Size( manager, &sfam->type.font, &face, &size ); if ( !error ) { /* by default, indicates a `missing' glyph */ sbit->buffer = 0; error = FT_Load_Glyph( face, gindex, sfam->type.flags | FT_LOAD_RENDER ); if ( !error ) { FT_Int temp; FT_GlyphSlot slot = face->glyph; FT_Bitmap* bitmap = &slot->bitmap; FT_Int xadvance, yadvance; /* check that our values fit into 8-bit containers! */ /* If this is not the case, our bitmap is too large */ /* and we will leave it as `missing' with sbit.buffer = 0 */ #define CHECK_CHAR( d ) ( temp = (FT_Char)d, temp == d ) #define CHECK_BYTE( d ) ( temp = (FT_Byte)d, temp == d ) /* XXX: FIXME: add support for vertical layouts maybe */ /* horizontal advance in pixels */ xadvance = ( slot->metrics.horiAdvance + 32 ) >> 6; yadvance = ( slot->metrics.vertAdvance + 32 ) >> 6; if ( CHECK_BYTE( bitmap->rows ) && CHECK_BYTE( bitmap->width ) && CHECK_CHAR( bitmap->pitch ) && CHECK_CHAR( slot->bitmap_left ) && CHECK_CHAR( slot->bitmap_top ) && CHECK_CHAR( xadvance ) && CHECK_CHAR( yadvance ) ) { sbit->width = (FT_Byte)bitmap->width; sbit->height = (FT_Byte)bitmap->rows; sbit->pitch = (FT_Char)bitmap->pitch; sbit->left = (FT_Char)slot->bitmap_left; sbit->top = (FT_Char)slot->bitmap_top; sbit->xadvance = (FT_Char)xadvance; sbit->yadvance = (FT_Char)yadvance; sbit->format = (FT_Byte)bitmap->pixel_mode; sbit->max_grays = (FT_Byte)(bitmap->num_grays - 1); #if 0 /* this doesn't work well with embedded bitmaps */ /* grab the bitmap when possible - this is a hack! */ if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) { slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; sbit->buffer = bitmap->buffer; } else #endif { /* copy the bitmap into a new buffer -- ignore error */ error = ftc_sbit_copy_bitmap( sbit, bitmap, memory ); } /* now, compute size */ if ( asize ) *asize = ABS( sbit->pitch ) * sbit->height; } /* glyph dimensions ok */ } /* glyph loading successful */