static void setup_fontparameters(PDF pdf, internal_font_number f, int ex_glyph) { float slant, extend, squeeze, expand, scale = 1.0; float u = 1.0; pdfstructure *p = pdf->pstruct; if ((font_format(f) == opentype_format || (font_format(f) == type1_format && font_encodingbytes(f) == 2)) && font_units_per_em(f) > 0) u = font_units_per_em(f) / 1000.0; pdf->f_cur = f; p->f_pdf = pdf_set_font(pdf, f); p->fs.m = i64round(font_size(f) / u / by_one_bp * ten_pow[p->fs.e]); slant = font_slant(f) / 1000.0; extend = font_extend(f) / 1000.0; squeeze = font_squeeze(f) / 1000.0; expand = 1.0 + (ex_glyph/1) / 1000.0; /*tex The |-1| makes less corrections inside |[]TJ|: */ p->tj_delta.e = p->cw.e - 1; /*tex There is no need to be more precise than \TEX\ (1sp). */ while (p->tj_delta.e > 0 && (double) font_size(f) / ten_pow[p->tj_delta.e + e_tj] < 0.5) { /*tex This happens for very tiny fonts. */ p->tj_delta.e--; } p->tm[0].m = i64round(scale * expand * extend * ten_pow[p->tm[0].e]); p->tm[2].m = i64round(slant * ten_pow[p->tm[2].e]); p->tm[3].m = i64round(scale * squeeze * ten_pow[p->tm[3].e]); p->k2 = ten_pow[e_tj + p->cw.e] * scale / (ten_pow[p->pdf.h.e] * pdf2double(p->fs) * pdf2double(p->tm[0])); /*tex We keep track of the state of ex. */ p->cur_ex = ex_glyph ; p->need_width = font_width(f); p->need_mode = font_mode(f); }
static const struct dfont_rect * gen_char(int unicode, const char * utf8, int size) { // todo : use large size when size is large struct font_context ctx; font_create(FONT_SIZE, &ctx); if (ctx.font == NULL) { return NULL; } font_size(utf8, unicode, &ctx); const struct dfont_rect * rect = dfont_insert(Dfont, unicode, FONT_SIZE, ctx.w+1, ctx.h+1); if (rect == NULL) { font_release(&ctx); return NULL; } ctx.w = rect->w ; ctx.h = rect->h ; int buffer_sz = ctx.w * ctx.h; ARRAY(uint8_t, buffer, buffer_sz); ARRAY(uint8_t, tmp, buffer_sz); memset(tmp,0,buffer_sz); font_glyph(utf8, unicode, tmp, &ctx); gen_outline(ctx.w, ctx.h, tmp, buffer); // write_pgm(unicode, ctx.w, ctx.h, buffer); font_release(&ctx); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexSubImage2D(GL_TEXTURE_2D, 0, rect->x, rect->y, rect->w, rect->h, TEX_FMT, GL_UNSIGNED_BYTE, buffer); return rect; }
static struct font_context char_size(int unicode, const char *utf8, int size, int edge) { const struct dfont_rect * rect = dfont_lookup(Dfont,unicode,FONT_SIZE,edge); struct font_context ctx; font_create(FONT_SIZE, &ctx); if (ctx.font == NULL) { ctx.w = 0; ctx.h = 0; return ctx; } if (rect == NULL) { font_size(utf8, unicode, &ctx); //see gen_char ctx.w += 1; ctx.h += 1; ctx.w = (ctx.w -1) * size / FONT_SIZE; ctx.h = ctx.h * size / FONT_SIZE; } else { ctx.w = (rect->w -1) * size / FONT_SIZE; ctx.h = rect->h * size / FONT_SIZE; } // font_release should not reset ctx.w/ctx.h font_release(&ctx); return ctx; }
static int getpdffontsize(lua_State * L) { if (lua_type(L, 1) == LUA_TNUMBER) { int c = (int) lua_tointeger(L, 1); lua_pushinteger(L, (font_size(c))); } else { lua_pushnil(L); } return 1 ; }
void print_font_identifier(internal_font_number f) { str_number fonttext; fonttext= font_id_text(f); if(fonttext> 0){ print_esc(fonttext); }else{ tprint_esc("FONT"); print_int(f); } if(tracing_fonts_par> 0){ tprint(" ("); print_font_name(f); if(font_size(f)!=font_dsize(f)){ tprint("@"); print_scaled(font_size(f)); tprint("pt"); } print_char(')'); } }
static const struct dfont_rect * gen_char(int unicode, const char * utf8, int size, int edge) { // todo : use large size when size is large struct font_context ctx; font_create(FONT_SIZE, &ctx); if (ctx.font == NULL) { return NULL; } font_size(utf8, unicode, &ctx); const struct dfont_rect * rect = dfont_insert(Dfont, unicode, FONT_SIZE, ctx.w+1, ctx.h+1, edge); if (rect == NULL) { dfont_flush(Dfont); rect = dfont_insert(Dfont, unicode, FONT_SIZE, ctx.w+1, ctx.h+1, edge); if (rect == NULL) { font_release(&ctx); return NULL; } } ctx.w = rect->w ; ctx.h = rect->h ; int buffer_sz = ctx.w * ctx.h; ARRAY(uint8_t, buffer, buffer_sz); #ifdef FONT_EDGE_HASH if (edge) { ARRAY(uint8_t, tmp, buffer_sz); memset(tmp,0,buffer_sz); font_glyph(utf8, unicode, tmp, &ctx); gen_outline(ctx.w, ctx.h, tmp, buffer); } else { memset(buffer,0,buffer_sz); font_glyph(utf8, unicode, buffer, &ctx); } #else ARRAY(uint8_t, tmp, buffer_sz); memset(tmp,0,buffer_sz); font_glyph(utf8, unicode, tmp, &ctx); gen_outline(ctx.w, ctx.h, tmp, buffer); #endif // write_pgm(unicode, ctx.w, ctx.h, buffer); font_release(&ctx); render_texture_subupdate(R, Tex, buffer, rect->x, rect->y, rect->w, rect->h); return rect; }
int main() { { TimeCheck time; constexpr int WIDTH = 450; constexpr int HEIGHT = 900; constexpr int STRIDE = WIDTH * 4; std::vector<unsigned char> datas(HEIGHT*STRIDE); auto surface = create_surface(datas, CAIRO_FORMAT_ARGB32, SURFACE_SIZE{ WIDTH, HEIGHT }, STRIDE); auto cr = create(surface); rectangle(cr, POINT{ 0,0 }, SIZE{ WIDTH ,HEIGHT }); source(cr, RGB{ 1,1,1 }); fill(cr); source(cr, RGB{ 0,0,0 }); font_face(cr, u8"serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); font_size(cr, 40); translate(cr, POINT{ 40, 40 }); font_face(cr, u8"mono", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); font_size(cr, 12); show_text(cr, u8"+CTM rotation"); constexpr auto NUM_STRINGS = 3; save(cr); { font_face(cr, u8"serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); font_size(cr, 40); for (int i = 0; i < NUM_STRINGS; ++i) { RADIAN angle{ i * 0.5*pi<double> / double(NUM_STRINGS - 1) }; save(cr); rotate(cr, angle); move_to(cr, POINT{ 100, 0 }); show_text(cr, u8"Text"); restore(cr); } } restore(cr); translate(cr, POINT{ 0, HEIGHT / 3 }); move_to(cr, POINT{ 0, 0 }); show_text(cr, u8"+CTM rotation"); rel_move_to(cr, POINT{ 0, 12 }); show_text(cr, u8"-font rotation"); save(cr); font_face(cr, u8"serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); font_size(cr, 40); { cairo_matrix_t mat{}; for (int i = 0; i < NUM_STRINGS; ++i) { RADIAN angle{ i * 0.5*pi<double> / double(NUM_STRINGS - 1) }; save(cr); rotate(cr, angle); identity(mat); scale(mat, SCALE{ 40,40 }); rotate(mat, -angle); font_matrix(cr, mat); move_to(cr, POINT{ 100, 0 }); show_text(cr, u8"Text"); restore(cr); } } restore(cr); translate(cr, POINT{ 0, HEIGHT / 3 }); move_to(cr, POINT{ 0, 0 }); show_text(cr, u8"+CTM rotation"); rel_move_to(cr, POINT{ 0, 12 }); show_text(cr, u8"-CTM rotation"); save(cr); font_face(cr, u8"serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); font_size(cr, 40); { for (int i = 0; i < NUM_STRINGS; ++i) { RADIAN angle{ i * 0.5*pi<double> / double(NUM_STRINGS - 1) }; save(cr); rotate(cr, angle); move_to(cr, POINT{ 100, 0 }); rotate(cr, -angle); show_text(cr, u8"Text"); restore(cr); } } restore(cr); write_to_png(surface, "image.png"); } return 0; }
int main(int argc, char** argv) { /* Window manager data structures. */ struct wm_device* dev = NULL; struct wm_window* win = NULL; const struct wm_window_desc win_desc = { 800, 600, 0 }; /* Renderer data structure. */ struct rdr_glyph_desc glyph_desc_list[NB_CHARS]; struct rdr_font* font = NULL; struct rdr_frame* frame = NULL; struct rdr_system* sys = NULL; struct rdr_term* term = NULL; /* Resources data structure. */ struct rsrc_context* ctxt = NULL; struct rsrc_font* rfont = NULL; /* Miscellaneous data. */ const char* driver_name = NULL; const char* font_name = NULL; size_t line_space = 0; size_t i = 0; bool b = false; if(argc != 3) { printf("usage: %s RB_DRIVER FONT\n", argv[0]); return -1; } driver_name = argv[1]; font_name = argv[2]; /* Setup the render font. */ RSRC(create_context(NULL, &ctxt)); RSRC(create_font(ctxt, font_name, &rfont)); if(RSRC(is_font_scalable(rfont, &b)), b) RSRC(font_size(rfont, 18, 18)); for(i = 0; i < NB_CHARS; ++i) { struct rsrc_glyph* glyph = NULL; struct rsrc_glyph_desc glyph_desc; size_t width = 0; size_t height = 0; size_t Bpp = 0; size_t size = 0; RSRC(font_glyph(rfont, (wchar_t)(i + FIRST_CHAR), &glyph)); /* Get glyph desc. */ RSRC(glyph_desc(glyph, &glyph_desc)); glyph_desc_list[i].width = glyph_desc.width; glyph_desc_list[i].character = glyph_desc.character; glyph_desc_list[i].bitmap_left = glyph_desc.bbox.x_min; glyph_desc_list[i].bitmap_top = glyph_desc.bbox.y_min; /* Get glyph bitmap. */ RSRC(glyph_bitmap(glyph, true, &width, &height, &Bpp, NULL)); glyph_desc_list[i].bitmap.width = width; glyph_desc_list[i].bitmap.height = height; glyph_desc_list[i].bitmap.bytes_per_pixel = Bpp; glyph_desc_list[i].bitmap.buffer = NULL; size = width * height * Bpp; if(0 != size) { unsigned char* buffer = MEM_CALLOC(&mem_default_allocator, 1, size); RSRC(glyph_bitmap(glyph, true, NULL, NULL, NULL, buffer)); glyph_desc_list[i].bitmap.buffer = buffer; } RSRC(glyph_ref_put(glyph)); } RSRC(font_line_space(rfont, &line_space)); RSRC(font_ref_put(rfont)); RSRC(context_ref_put(ctxt)); WM(create_device(NULL, &dev)); WM(create_window(dev, &win_desc, &win)); RDR(create_system(driver_name, NULL, &sys)); RDR(create_frame (sys, (struct rdr_frame_desc[]){{win_desc.width,win_desc.height}}, &frame));
void do_vf_packet (internal_font_number vf_f, integer c) { internal_font_number lf; charinfo *co; scaled save_cur_h, save_cur_v; real_eight_bits *vf_packets; integer cur_packet_byte; integer cmd, fs_f; scaled i; unsigned k; str_number s; packet_cur_s++; if (packet_cur_s >= packet_max_recursion) overflow_string("max level recursion of virtual fonts", packet_max_recursion); save_cur_v = cur_v; save_cur_h = cur_h; lf = 0; /* for -Wall */ co = get_charinfo(vf_f,c); vf_packets = get_charinfo_packets(co); if (vf_packets == NULL) { packet_cur_s--; return ; } cur_packet_byte = 0; fs_f = font_size(vf_f); while ((cmd = vf_packets[cur_packet_byte]) != packet_end_code) { cur_packet_byte++; /* if (cmd>packet_end_code) { fprintf(stdout, "do_vf_packet(%i,%i) command code = illegal \n", vf_f,c); } else { fprintf(stdout, "do_vf_packet(%i,%i) command code = %s\n",vf_f, c, packet_command_names[cmd]); } */ switch (cmd) { case packet_font_code: packet_number(lf); break; case packet_push_code: packet_stack[packet_stack_ptr].stack_h = cur_h; packet_stack[packet_stack_ptr].stack_v = cur_v; packet_stack_ptr++; break; case packet_pop_code: packet_stack_ptr--; cur_h = packet_stack[packet_stack_ptr].stack_h; cur_v = packet_stack[packet_stack_ptr].stack_v; break; case packet_char_code: packet_number(k); if (!char_exists(lf,k)) { char_warning(lf, k); } else { output_one_char(lf, k); } cur_h = cur_h + char_width(lf,k); break; case packet_rule_code: packet_scaled(rule_ht,fs_f); packet_scaled(rule_wd,fs_f); if ((rule_wd > 0) && (rule_ht > 0)) { pdf_set_rule(cur_h, cur_v, rule_wd, rule_ht); cur_h = cur_h + rule_wd; } break; case packet_right_code: packet_scaled(i,fs_f); cur_h = cur_h + i; break; case packet_down_code: packet_scaled(i,fs_f); cur_v = cur_v + i; break; case packet_special_code: packet_number(k); string_room(k); while (k > 0) { k--; append_pool_char(do_packet_byte()); } s = make_string(); literal(s, scan_special, false); flush_str(s); break; case packet_node_code: packet_number(k); temp_ptr = k; pdf_hlist_out(); break; case packet_nop_code: break; default: pdf_error(maketexstring("vf"), maketexstring("invalid DVI command")); } }; cur_h = save_cur_h; cur_v = save_cur_v; packet_cur_s--; }
static int64_t pdf_char_width(pdfstructure * p, internal_font_number f, int i) { return i64round((double) char_width(f, i) / font_size(f) * ten_pow[e_tj + p->cw.e]); }