X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=blobdiff_plain;f=lib%2Fruby%2Fgfx.c;h=9384d1904be9731026911339652c1fc64a8a62ad;hp=a963bc1d11d024b0408f9aa2b560934e8eec63d4;hb=2ddfa640af28b592ecf4295f0b1b7b43c923f707;hpb=e1563f533b093d998c898faafb2eb5d644e85dd7 diff --git a/lib/ruby/gfx.c b/lib/ruby/gfx.c index a963bc1..9384d19 100644 --- a/lib/ruby/gfx.c +++ b/lib/ruby/gfx.c @@ -2,6 +2,7 @@ #include "../gfxdevice.h" #include "../gfxsource.h" #include "../gfxtools.h" +#include "../gfximage.h" #include "../devices/pdf.h" #include "../readers/swf.h" #include "../readers/image.h" @@ -28,19 +29,21 @@ typedef struct page_internal { } page_internal_t; typedef struct image_internal { + doc_internal_t*doc; gfximage_t*image; } image_internal_t; -typedef struct glyph_internal { - gfxfont_t*font; - int nr; -} glyph_internal_t; - typedef struct font_internal { + VALUE self; VALUE glyph_array; gfxfont_t*font; } font_internal_t; +typedef struct glyph_internal { + font_internal_t*font; + int nr; +} glyph_internal_t; + static gfxsource_t* pdfdriver = 0; static gfxsource_t* imagedriver = 0; static gfxsource_t* swfdriver = 0; @@ -60,6 +63,9 @@ static VALUE doc_initialize(VALUE cls, VALUE _filename) const char*filename = StringValuePtr(_filename); doc->fontlist = gfxfontlist_create(); doc->doc = pdfdriver->open(pdfdriver, filename); + if(!doc->doc) { + rb_raise(rb_eIOError, "couldn't open %s", filename); + } return cls; } @@ -177,10 +183,14 @@ static void image_free(image_internal_t*image) { free(image); } +static void image_mark(image_internal_t*image) +{ + rb_gc_mark(image->doc->self); +} static VALUE image_allocate(VALUE cls) { image_internal_t*image = 0; - VALUE v = Data_Make_Struct(cls, image_internal_t, 0, image_free, image); + VALUE v = Data_Make_Struct(cls, image_internal_t, image_mark, image_free, image); memset(image, 0, sizeof(image_internal_t)); return v; } @@ -194,25 +204,42 @@ static VALUE image_height(VALUE cls) Get_Image(image,cls) return INT2FIX(image->image->height); } +static VALUE image_rescale(VALUE cls, VALUE _width, VALUE _height) +{ + Get_Image(image,cls) + Check_Type(_width, T_FIXNUM); + Check_Type(_height, T_FIXNUM); + int width = FIX2INT(_width); + int height = FIX2INT(_height); + volatile VALUE v_image2 = image_allocate(Bitmap); + Get_Image(image2,v_image2) + image2->doc = image->doc; + image2->image = gfximage_rescale(image->image, width, height); + return v_image2; +} static VALUE image_save_jpeg(VALUE cls, VALUE _filename, VALUE quality) { Get_Image(image,cls) Check_Type(_filename, T_STRING); Check_Type(quality, T_FIXNUM); const char*filename = StringValuePtr(_filename); - int l = strlen(filename); - char jpeg = 0; - if(l>=4 && !strcmp(&filename[l-4], ".jpg")) jpeg = 1; - if(l>=5 && !strcmp(&filename[l-5], ".jpeg")) jpeg = 1; - if(l>=4 && !strcmp(&filename[l-4], ".JPG")) jpeg = 1; - jpeg_save(image->image->data, image->image->width, image->image->height, FIX2INT(quality), filename); + gfximage_save_jpeg(image->image, filename, FIX2INT(quality)); return cls; } -VALUE convert_image(gfximage_t*_image) +static VALUE image_save_png(VALUE cls, VALUE _filename) +{ + Get_Image(image,cls) + Check_Type(_filename, T_STRING); + const char*filename = StringValuePtr(_filename); + gfximage_save_png(image->image, filename); + return cls; +} +VALUE convert_image(doc_internal_t*doc,gfximage_t*_image) { VALUE v = image_allocate(Bitmap); Get_Image(image,v) image->image = _image; + image->doc = doc; return v; } void invalidate_image(VALUE v) @@ -232,10 +259,15 @@ static void glyph_free(glyph_internal_t*glyph) free(glyph); } +static void glyph_mark(glyph_internal_t*glyph) +{ + rb_gc_mark(glyph->font->self); +} + static VALUE glyph_allocate(VALUE cls) { glyph_internal_t*glyph = 0; - VALUE v = Data_Make_Struct(cls, glyph_internal_t, 0, glyph_free, glyph); + VALUE v = Data_Make_Struct(cls, glyph_internal_t, glyph_mark, glyph_free, glyph); memset(glyph, 0, sizeof(glyph_internal_t)); return v; } @@ -243,19 +275,29 @@ static VALUE glyph_allocate(VALUE cls) static VALUE glyph_polygon(VALUE cls) { Get_Glyph(glyph,cls); - return convert_line(glyph->font->glyphs[glyph->nr].line); + return convert_line(glyph->font->font->glyphs[glyph->nr].line); } static VALUE glyph_advance(VALUE cls) { Get_Glyph(glyph,cls); - return rb_float_new(glyph->font->glyphs[glyph->nr].advance); + return rb_float_new(glyph->font->font->glyphs[glyph->nr].advance); +} + +static VALUE glyph_bbox(VALUE cls) +{ + Get_Glyph(glyph,cls); + gfxbbox_t bbox = gfxline_getbbox(glyph->font->font->glyphs[glyph->nr].line); + return rb_ary_new3(4, rb_float_new(bbox.xmin), + rb_float_new(bbox.ymin), + rb_float_new(bbox.xmax), + rb_float_new(bbox.ymax)); } static VALUE glyph_unicode(VALUE cls) { Get_Glyph(glyph,cls); - return INT2FIX(glyph->font->glyphs[glyph->nr].unicode); + return INT2FIX(glyph->font->font->glyphs[glyph->nr].unicode); } // ------------------------ font -------------------------------------------- @@ -277,9 +319,22 @@ static VALUE font_allocate(VALUE cls) font_internal_t*font = 0; VALUE v = Data_Make_Struct(cls, font_internal_t, font_mark, font_free, font); memset(font, 0, sizeof(font_internal_t)); + font->self = v; return v; } +static VALUE font_ascent(VALUE cls) +{ + Get_Font(font,cls); + return rb_float_new(font->font->ascent); +} + +static VALUE font_descent(VALUE cls) +{ + Get_Font(font,cls); + return rb_float_new(font->font->descent); +} + static VALUE font_name(VALUE cls) { Get_Font(font,cls); @@ -292,6 +347,23 @@ static VALUE font_glyphs(VALUE cls) return font->glyph_array; } +static VALUE font_kerning(VALUE cls) +{ + Get_Font(font,cls); + gfxkerning_t*kerning = font->font->kerning; + int kerning_size = font->font->kerning_size; + volatile VALUE a = rb_ary_new2(kerning_size); + int t; + for(t=0;tnext;len++;} - VALUE array = rb_ary_new2(len); - rb_gc_register_address(&array); + volatile VALUE array = rb_ary_new2(len); int pos = 0; l = line; while(l) { - VALUE e; + volatile VALUE e; if(l->type == gfx_moveTo) { e = rb_ary_new3(3, ID2SYM(id_move), Qfalse, Qfalse); rb_ary_store(array, pos, e); @@ -362,7 +433,6 @@ VALUE convert_line(gfxline_t*line) pos++; l=l->next; } - rb_gc_unregister_address(&array); return array; } VALUE convert_color(gfxcolor_t*color) @@ -371,9 +441,8 @@ VALUE convert_color(gfxcolor_t*color) } VALUE convert_matrix(gfxmatrix_t*matrix) { - VALUE array = rb_ary_new2(3); - rb_gc_register_address(&array); - VALUE a = rb_ary_new2(2); + volatile VALUE array = rb_ary_new2(3); + volatile VALUE a = rb_ary_new2(2); rb_ary_store(array, 0, a); rb_ary_store(a, 0, rb_float_new(matrix->m00)); rb_ary_store(a, 1, rb_float_new(matrix->m01)); @@ -385,29 +454,31 @@ VALUE convert_matrix(gfxmatrix_t*matrix) rb_ary_store(array, 2, a); rb_ary_store(a, 0, rb_float_new(matrix->tx)); rb_ary_store(a, 1, rb_float_new(matrix->ty)); - rb_gc_unregister_address(&array); return array; } -VALUE convert_font(device_internal_t*i, gfxfont_t*font) +static VALUE font_is_cached(device_internal_t*i, gfxfont_t*font) +{ + return (VALUE)gfxfontlist_getuserdata(i->doc->fontlist, font->id); +} +static void cache_font(device_internal_t*i, gfxfont_t*font, VALUE v) +{ + i->doc->fontlist = gfxfontlist_addfont2(i->doc->fontlist, font, (void*)v); +} +static VALUE convert_font(gfxfont_t*font) { - VALUE v = (VALUE)gfxfontlist_getuserdata(i->doc->fontlist, font->id); - if(v) return v; + volatile VALUE v2 = font_allocate(Font); + Get_Font(f, v2); + f->font = font; + f->glyph_array = rb_ary_new2(font->num_glyphs); - VALUE*a = (VALUE*)malloc(sizeof(VALUE)*font->num_glyphs); int t; for(t=0;tnum_glyphs;t++) { - a[t] = glyph_allocate(Glyph); - Get_Glyph(g, a[t]); - g->font = font; + volatile VALUE a = glyph_allocate(Glyph); + rb_ary_store(f->glyph_array, t, a); + Get_Glyph(g, a); + g->font = f; g->nr = t; } - VALUE v2 = font_allocate(Font); - Get_Font(f, v2); - - f->font = font; - f->glyph_array = rb_ary_new4(font->num_glyphs, a); - - i->doc->fontlist = gfxfontlist_addfont2(i->doc->fontlist, font, (void*)v2); return v2; } #define HEAD \ @@ -416,7 +487,9 @@ VALUE convert_font(device_internal_t*i, gfxfont_t*font) int rb_setparameter(gfxdevice_t*dev, const char*key, const char*value) { HEAD - VALUE ret = forward(v,id_setparameter,2,rb_tainted_str_new2(key),rb_tainted_str_new2(value)); + volatile VALUE v_key = rb_tainted_str_new2(key); + volatile VALUE v_value = rb_tainted_str_new2(value); + VALUE ret = forward(v,id_setparameter,2,v_key,v_value); return 0; } void rb_startpage(gfxdevice_t*dev, int width, int height) @@ -427,7 +500,8 @@ void rb_startpage(gfxdevice_t*dev, int width, int height) void rb_startclip(gfxdevice_t*dev, gfxline_t*line) { HEAD - VALUE ret = forward(v,id_startclip,1,convert_line(line)); + volatile VALUE v_line = convert_line(line); + VALUE ret = forward(v,id_startclip,1,v_line); } void rb_endclip(gfxdevice_t*dev) { @@ -448,49 +522,27 @@ void rb_stroke(gfxdevice_t*dev, gfxline_t*line, gfxcoord_t width, gfxcolor_t*col else if(joint_style == gfx_joinMiter) joint = id_miter; else if(joint_style == gfx_joinBevel) joint = id_bevel; - VALUE v_line = convert_line(line); - rb_gc_register_address(&v_line); - VALUE v_width = rb_float_new(width); - rb_gc_register_address(&v_width); - VALUE v_color = convert_color(color); - rb_gc_register_address(&v_color); - VALUE v_miter = rb_float_new(miterLimit); - rb_gc_register_address(&v_miter); - + volatile VALUE v_line = convert_line(line); + volatile VALUE v_width = rb_float_new(width); + volatile VALUE v_color = convert_color(color); + volatile VALUE v_miter = rb_float_new(miterLimit); forward(v, id_stroke, 6, v_line, v_width, v_color, ID2SYM(cap), ID2SYM(joint), v_miter); - - rb_gc_unregister_address(&v_miter); - rb_gc_unregister_address(&v_color); - rb_gc_unregister_address(&v_width); - rb_gc_unregister_address(&v_line); } void rb_fill(gfxdevice_t*dev, gfxline_t*line, gfxcolor_t*color) { HEAD - VALUE v_line = convert_line(line); - rb_gc_register_address(&v_line); - VALUE v_color = convert_color(color); - rb_gc_register_address(&v_color); - + volatile VALUE v_line = convert_line(line); + volatile VALUE v_color = convert_color(color); forward(v, id_fill, 2, v_line, v_color); - - rb_gc_unregister_address(&v_color); - rb_gc_unregister_address(&v_line); } void rb_fillbitmap(gfxdevice_t*dev, gfxline_t*line, gfximage_t*img, gfxmatrix_t*matrix, gfxcxform_t*cxform) { HEAD - VALUE v_image = convert_image(img); - rb_gc_register_address(&v_image); - VALUE v_line = convert_line(line); - rb_gc_register_address(&v_line); - VALUE v_matrix = convert_matrix(matrix); - rb_gc_register_address(&v_matrix); + volatile VALUE v_image = convert_image(i->doc, img); + volatile VALUE v_line = convert_line(line); + volatile VALUE v_matrix = convert_matrix(matrix); forward(v, id_fillbitmap, 4, v_line, v_image, v_matrix, Qnil); - rb_gc_unregister_address(&v_matrix); - rb_gc_unregister_address(&v_line); - rb_gc_unregister_address(&v_image); invalidate_image(v_image); } void rb_fillgradient(gfxdevice_t*dev, gfxline_t*line, gfxgradient_t*gradient, gfxgradienttype_t type, gfxmatrix_t*matrix) @@ -498,31 +550,36 @@ void rb_fillgradient(gfxdevice_t*dev, gfxline_t*line, gfxgradient_t*gradient, gf HEAD ID typeid = (type == gfxgradient_linear)? id_linear : id_radial; - VALUE v_line = convert_line(line); - rb_gc_register_address(&v_line); - VALUE v_matrix = convert_matrix(matrix); - rb_gc_register_address(&v_matrix); - VALUE v_gradient = convert_gradient(gradient); - rb_gc_register_address(&v_gradient); - forward(v, id_fillgradient, 4, v_line, v_gradient, ID2SYM(typeid), convert_matrix(matrix)); - rb_gc_unregister_address(&v_gradient); - rb_gc_unregister_address(&v_matrix); - rb_gc_unregister_address(&v_line); + volatile VALUE v_line = convert_line(line); + volatile VALUE v_matrix = convert_matrix(matrix); + volatile VALUE v_gradient = convert_gradient(gradient); + forward(v, id_fillgradient, 4, v_line, v_gradient, ID2SYM(typeid), v_matrix); } void rb_addfont(gfxdevice_t*dev, gfxfont_t*font) { HEAD - forward(v, id_addfont, 1, convert_font(i, font)); + + volatile VALUE f = font_is_cached(i, font); + if(!f) {f=convert_font(font);cache_font(i,font,f);} + + forward(v, id_addfont, 1, f); } void rb_drawchar(gfxdevice_t*dev, gfxfont_t*font, int glyphnr, gfxcolor_t*color, gfxmatrix_t*matrix) { HEAD - forward(v, id_drawchar, 4, convert_font(i, font), INT2FIX(glyphnr), convert_color(color), convert_matrix(matrix)); + volatile VALUE f = font_is_cached(i, font); + if(!f) {f=convert_font(font);cache_font(i,font,f);} + + volatile VALUE v_color = convert_color(color); + volatile VALUE v_matrix = convert_matrix(matrix); + forward(v, id_drawchar, 4, f, INT2FIX(glyphnr), v_color, v_matrix); } void rb_drawlink(gfxdevice_t*dev, gfxline_t*line, const char*action) { HEAD - forward(v, id_drawlink, convert_line(line), rb_tainted_str_new2(action)); + volatile VALUE v_line = convert_line(line); + volatile VALUE v_action = rb_tainted_str_new2(action); + forward(v, id_drawlink, v_line, v_action); } void rb_endpage(gfxdevice_t*dev) { @@ -563,11 +620,26 @@ static VALUE page_render(VALUE cls, VALUE device) dev.endpage = rb_endpage; dev.finish = rb_finish; + dev.startpage(&dev, page->page->width, page->page->height); page->page->render(page->page, &dev); + dev.endpage(&dev); return cls; } +// ---------------------- global functions ---------------------------------- + +VALUE gfx_setparameter(VALUE module, VALUE _key, VALUE _value) +{ + Check_Type(_key, T_STRING); + Check_Type(_value, T_STRING); + const char*key = StringValuePtr(_key); + const char*value = StringValuePtr(_value); + pdfdriver->setparameter(pdfdriver, key, value); + swfdriver->setparameter(swfdriver, key, value); + imagedriver->setparameter(imagedriver, key, value); + return GFX; +} // -------------------------------------------------------------------------- @@ -580,6 +652,8 @@ void Init_gfx() GFX = rb_define_module("GFX"); + rb_define_module_function(GFX, "setparameter", gfx_setparameter, 2); + DocumentPage = rb_define_class_under(GFX, "DocumentPage", rb_cObject); rb_define_method(DocumentPage, "width", page_width, 0); rb_define_method(DocumentPage, "height", page_height, 0); @@ -593,15 +667,24 @@ void Init_gfx() Bitmap = rb_define_class_under(GFX, "Bitmap", rb_cObject); rb_define_method(Bitmap, "save_jpeg", image_save_jpeg, 2); + rb_define_method(Bitmap, "save_png", image_save_png, 1); + rb_define_method(Bitmap, "width", image_width, 0); + rb_define_method(Bitmap, "height", image_height, 0); + rb_define_method(Bitmap, "rescale", image_rescale, 2); Glyph = rb_define_class_under(GFX, "Glyph", rb_cObject); rb_define_method(Glyph, "polygon", glyph_polygon, 0); rb_define_method(Glyph, "unicode", glyph_unicode, 0); rb_define_method(Glyph, "advance", glyph_advance, 0); + rb_define_method(Glyph, "bbox", glyph_bbox, 0); Font = rb_define_class_under(GFX, "Font", rb_cObject); rb_define_method(Font, "name", font_name, 0); + rb_define_method(Font, "ascent", font_ascent, 0); + rb_define_method(Font, "descent", font_descent, 0); rb_define_method(Font, "glyphs", font_glyphs, 0); + rb_define_method(Font, "kerning", font_kerning, 0); + rb_define_method(Font, "get_kerning_table", font_kerning, 0); Device = rb_define_class_under(GFX, "Device", rb_cObject); rb_define_method(Device, "startpage", noop, -1);