static void redraw(void) { if (!frontbuffer || !backbuffer) return; for (int y = 0; y<screenheight; y++) { unsigned int* frontp = &frontbuffer[y * screenwidth]; unsigned int* backp = &backbuffer[y * screenwidth]; for (int x = 0; x<screenwidth; x++) { if (frontp[x] != backp[x]) { frontp[x] = backp[x]; render_glyph(frontp[x], x, y); } } } /* Draw a caret where the cursor should be. */ int x = cursorx*fontwidth - 1; if (x < 0) x = 0; int y = cursory*fontheight; int h = fontheight; XftColor* c = &colours[COLOUR_BRIGHT]; XftDrawRect(draw, c, x, y, 1, h); XftDrawRect(draw, c, x-1, y-1, 1, 1); XftDrawRect(draw, c, x+1, y-1, 1, 1); XftDrawRect(draw, c, x-1, y+h, 1, 1); XftDrawRect(draw, c, x+1, y+h, 1, 1); }
bitmap_info* glyph_provider_tu::get_char_image(character_def* shape_glyph, Uint16 xcode, const tu_string& fontname, bool is_bold, bool is_italic, int fontsize, rect* bounds, float* advance) { shape_character_def* sh = cast_to<shape_character_def>(shape_glyph); if (sh == NULL) { return NULL; } int flags = is_bold ? 2 : 0; flags |= is_italic ? 1 : 0; int glyph_code = (Uint8) fontsize << 24 | (Uint8) flags << 16 | xcode; glyph_array* ga; glyph_entity ge; if (m_glyph.get(fontname, &ga)) { if (ga->get(glyph_code, &ge)) { if (bounds) { *bounds = ge.m_bounds; } if (advance) { *advance = ge.m_advance; } // printf("glyph_provider_tu: finded %08X: %s\n", glyph_code, fontname.c_str()); return ge.m_bi; } } else { // add new font // printf("glyph_provider_tu: added font %s\n", fontname.c_str()); ga = new glyph_array(); m_glyph[fontname] = ga; } render_glyph(&ge, sh, fontsize); // store glyph ge.m_advance = 0; ga->add(glyph_code, ge); if (bounds) { *bounds = ge.m_bounds; } if (advance) { *advance = ge.m_advance; } // printf("glyph_provider_tu: added %08X: %s\n", glyph_code, fontname.c_str()); return ge.m_bi; }
int render_text(SDL_Renderer *renderer, Scene *scene, Glyph *glyphs, int nglyphs) { int i, pos, baseline; SDL_Surface *glyph_sur; pos = 0; scene->nglyphs = 0; for (i = 0; i < nglyphs; i++) { baseline = render_glyph(&glyphs[i], &glyph_sur); scene->glyphs[i] = SDL_CreateTextureFromSurface(renderer, glyph_sur); scene->rects[i].x = pos; scene->rects[i].y = baseline; scene->rects[i].w = glyph_sur->w; scene->rects[i].h = glyph_sur->h; pos += glyph_sur->w; scene->nglyphs++; SDL_FreeSurface(glyph_sur); } return 0; }
int main(int argc, const char* argv[]) { size_t tex_side =(argc>1)? std::atoi(argv[1]) : 512; const char* font_desc_str = (argc>2)? argv[2] : "Sans 18"; unsigned plane = (argc>3)? std::atoi(argv[3]) : 0; cairo_surface_t *surface = cairo_image_surface_create( CAIRO_FORMAT_A8, tex_side, tex_side ); cairo_t *cr = cairo_create(surface); PangoFontDescription *font_desc = pango_font_description_from_string( font_desc_str ); PangoFontMap* font_map = pango_cairo_font_map_get_default(); PangoContext* context = pango_font_map_create_context(font_map); PangoFont* font = pango_font_map_load_font( font_map, context, font_desc ); PangoFontMetrics* font_metrics = pango_font_get_metrics(font, nullptr); // The Bitmap Glyph Metrics file std::ofstream bgm((argc>5) ? argv[5] : "out.bgm"); unsigned step = tex_side / 16; for(unsigned y=0; y!=16; ++y) { for(unsigned x=0; x!=16; ++x) { render_glyph( cr, font_desc, font, 256*plane + y*16 + x, x, y, step, tex_side, pango_font_metrics_get_ascent(font_metrics), pango_font_metrics_get_descent(font_metrics), bgm ); } } bgm.close(); pango_font_metrics_unref(font_metrics); pango_font_description_free(font_desc); g_object_unref(context); cairo_destroy(cr); cairo_status_t status = cairo_surface_write_to_png( surface, (argc>4) ? argv[4] : "out.png" ); cairo_surface_destroy(surface); return 0; }
SDL_Surface * Text::render_glyph_large_gray(const char g) { return render_glyph(font_large, GLYPH_LARGE_W, GLYPH_LARGE_H, g, true); }
SDL_Surface * Text::render_glyph_medium_gray(const char g) { return render_glyph(font_medium, GLYPH_MEDIUM_W, GLYPH_MEDIUM_H, g, true); }
/* Glyph gray */ SDL_Surface * Text::render_glyph_small_gray(const char g) { return render_glyph(font_small, GLYPH_SMALL_W, GLYPH_SMALL_H, g, true); }
/* Render the string beginning from the specified x offset (in pixels) */ int framebuffer_render_text(char *s, glyphtable_t *glyph_table, color_t *gbuf, size_t gbufwidth, size_t gbufheight, size_t offx){ unsigned int len = strlen(s); char *p = s; if(!setlocale(LC_CTYPE, "en_US.utf8")){ fprintf(stderr, "Cannot set locale\n"); goto error; } memset(gbuf, 0, gbufwidth*gbufheight*sizeof(color_t)); unsigned int x = 0; wchar_t c; p = s; mbstate_t ps = {0}; memset(&ps, 0, sizeof(mbstate_t)); struct { color_t fg; color_t bg; unsigned int blink:4; unsigned int bold:1; /* TODO */ unsigned int underline:1; unsigned int strikethrough:1; unsigned int fraktur:1; /* TODO See: Flat10 Fraktur font */ unsigned int invert:1; } style = { colortable[DEFAULT_FG_COLOR], colortable[DEFAULT_BG_COLOR], 0, 0, 0, 0, 0, 0 }; /* Render glyphs (now with escape sequence rendering!) */ for(;;){ /* NOTE: This nested escape sequence parsing does not contain any unicode-awareness whatsoever */ if(*p == '\033'){ /* Escape sequence YAY */ char *sequence_start = ++p; if(*p == '['){ /* This was a CSI! */ /* Disassemble the list of numbers, only accept SGR sequences (those ending with 'm') */ long elems[MAX_CSI_ELEMENTS]; int nelems; for(nelems = 0; nelems<MAX_CSI_ELEMENTS; nelems++){ p++; char *endptr; elems[nelems] = strtol(p, &endptr, 10); if(p == endptr){ fprintf(stderr, "Invalid escape sequence: \"\\e%s\"\n", sequence_start); goto error; } p = endptr; if(*endptr == 'm') break; if(*endptr != ';'){ fprintf(stderr, "Invalid escape sequence: \"\\e%s\"\n", sequence_start); goto error; } } p++; /* gobble up trailing 'm' of "\033[23;42m" */ nelems++; /* By now we know it's a SGR since we error'ed out on anything else */ if(nelems < 1){ fprintf(stderr, "Unsupported escape sequence: \"\\e%s\"\n", sequence_start); goto error; } /* Parse the sequence numbers */ for(int i=0; i<nelems; i++){ switch(elems[i]){ case 0: /* reset style */ style.fg = colortable[DEFAULT_FG_COLOR]; style.bg = colortable[DEFAULT_BG_COLOR]; style.bold = 0; style.underline = 0; style.blink = 0; style.strikethrough = 0; style.fraktur = 0; style.invert = 0; break; case 1: /* bold */ style.bold = 1; break; case 4: /* underline */ style.underline = 1; break; case 5: /* slow blink */ style.blink = 1; break; case 6: /* rapid blink */ style.blink = 8; break; case 7: /* color invert on */ style.invert = 1; break; case 9: /* strike-through */ style.strikethrough = 1; break; case 20:/* Fraktur */ style.fraktur = 1; break; case 22:/* Bold off */ style.bold = 0; break; case 24:/* Underline off */ style.underline = 0; break; case 25:/* Blink off */ style.blink = 0; break; case 27:/* color invert off */ style.invert = 0; break; case 29:/* strike-through off */ style.strikethrough = 0; break; case 30: /* Set foreground color, "dim" colors */ case 31: case 32: case 33: case 34: case 35: case 36: case 37: style.fg = colortable[elems[i]-30]; break; case 38: /* Set xterm-256 foreground color */ i++; if(nelems-i < 2 || elems[i] != 5){ fprintf(stderr, "Invalid ANSI escape code: \"\\e%s\"\n", sequence_start); goto error; } style.fg = colortable[elems[++i]]; break; case 39: /* Reset foreground color to default */ style.bg = colortable[DEFAULT_FG_COLOR]; break; case 40: /* Set background color, "dim" colors */ case 41: case 42: case 43: case 44: case 45: case 46: case 47: style.bg = colortable[elems[i]-40]; break; case 48: /* Set xterm-256 background color */ i++; if(nelems-i < 2 || elems[i] != 5){ fprintf(stderr, "Invalid ANSI escape code: \"\\e%s\"\n", sequence_start); goto error; } style.bg = colortable[elems[++i]]; break; case 49: /* Reset background color to default */ style.bg = colortable[DEFAULT_BG_COLOR]; break; case 90: /* Set foreground color, "bright" colors */ case 91: case 92: case 93: case 94: case 95: case 96: case 97: style.fg = colortable[elems[i]-90+8]; break; case 100: /* Set background color, "bright" colors */ case 101: case 102: case 103: case 104: case 105: case 106: case 107: style.bg = colortable[elems[i]-100+8]; break; default: fprintf(stderr, "Unsupported escape sequence: \"\\e%s\"\n", sequence_start); goto error; } } }else{ fprintf(stderr, "Unsupported escape sequence: \"\\e%s\"\n", sequence_start); goto error; } continue; } size_t inc = mbrtowc(&c, p, (s+len+1)-p, NULL); /* If p contained */ if(inc == 0) /* Reached end of string */ break; p += inc; /* Render glyph into frame buffer */ struct timeb time = {0}; ftime(&time); unsigned long int t = time.time*1000 + time.millitm; int blink = style.blink && (t % (1000/style.blink) < (333/style.blink)); int inv = !(style.invert ^ blink); color_t fg = inv ? style.fg : style.bg; color_t bg = inv ? style.bg : style.fg; glyph_t *g = glyph_table->data[c]; /* Is the glyph within the buffer's bounds? */ //if(x+g->width > offx && x < offx+gbufwidth){ /* x-offx might be negative down to -g->width+1, but that's ok */ render_glyph(g, gbuf, gbufwidth, x-offx, 0, fg, bg); if(style.strikethrough || style.underline){ int sty = gbufheight/2; /* g->y usually is a negative index of the glyph's baseline measured from the glyph's bottom */ int uly = gbufheight + g->y; for(int i=0; i<g->width; i++){ if(x+i >= offx && x+i-offx < gbufwidth){ /* Stay within the frame buffer's bounds */ if(style.strikethrough) gbuf[sty*gbufwidth + x + i - offx] = fg; if(style.underline) gbuf[uly*gbufwidth + x + i - offx] = fg; } } } //} x += g->width; } return 0; error: return 1; }
int main (int argc, char **argv) { int i; // 处理命令行参数,获取下列信息 // 字库文件名 // 显示字体象素大小 // 分辨率 // 是否使用灰度显示 // 将显示的文本 parse_args (argc, argv); // 初始化一个新的 FreeType 库对象 library error = FT_Init_FreeType (&library); if (error) fatal_error ("couldn't initialize FreeType library."); // 为字库文件 font_filename 中的第一种字体创建一个新的字体对象 face error = FT_New_Face (library, font_filename, 0, &face); if (error == FT_Err_Unknown_File_Format) fatal_error ("unsupported font format in file '%s'.", font_filename); else if (error) fatal_error ("unable to open input file '%s'.", font_filename); // 选择字体对象 face 中的 Unicode 字符码表为缺省码表 error = FT_Select_Charmap (face, ft_encoding_unicode); if (error) fatal_error ("couldn't select Unicode charmap."); // 设置字体 face 的字符宽度和高度都为 pixel_size 个象素 // 水平和垂直分辨率都为 resolution dpi error = FT_Set_Char_Size (face, pixel_size * 64, pixel_size * 64, resolution, resolution); if (error) fatal_error ("couldn't set character size: pixel size %d, resolution %d.", pixel_size, resolution); // 把将显示的文本转换为 Unicode 编码 text_to_unicode (); // 初始化 X 窗口 init_display (); // 对以 Unicode 编码的文本中所有字符进行逐一处理 for (i = 0; i < num_glyphs; i++) { // 生成第 i 个 Unicode 字符的字形图象的位图(单色图或灰度图) render_glyph (unicode_text[i], grayscale); // 生成第 i 个字形的 X 图象(XImage),并保存下列信息: // 字形位图的左边轴距 // 字形位图的顶边轴距 // 字形的水平步幅 // 字形的垂直步幅 render_image (i, face->glyph->bitmap.buffer, face->glyph->bitmap.rows, face->glyph->bitmap.pitch, face->glyph->bitmap_left, face->glyph->bitmap_top, face->glyph->advance.x / 64, face->glyph->advance.y / 64, grayscale); } // 在 X 窗口中,从位置 x = 0,y = pixel_size * resolution / 72 // 开始画出文本的所有字符的图象 draw_image (0, pixel_size * resolution / 72); // X 事件循环 event_loop (); // 销毁字体对象 face 及它的所有子对象 FT_Done_Face (face); // 销毁 FreeType 库对象 library 及它的所有后代 FT_Done_FreeType (library); return 0; }