From e1563f533b093d998c898faafb2eb5d644e85dd7 Mon Sep 17 00:00:00 2001 From: Matthias Kramm Date: Fri, 18 Dec 2009 19:34:11 -0800 Subject: [PATCH] fixed some memory issues in ruby interface --- lib/ruby/gfx.c | 190 +++++++++++++++++++++++++++++++++++++++++++++--------- lib/ruby/test.rb | 21 +++--- 2 files changed, 168 insertions(+), 43 deletions(-) diff --git a/lib/ruby/gfx.c b/lib/ruby/gfx.c index a7a8766..a963bc1 100644 --- a/lib/ruby/gfx.c +++ b/lib/ruby/gfx.c @@ -12,16 +12,18 @@ #define RUBY_GFX_VERSION "0.9.0" static VALUE GFX; -static VALUE Glyph, Bitmap, Document, DocumentPage, PDFClass, SWFClass, ImageClass, Device; +static VALUE Font, Glyph, Bitmap, Document, DocumentPage, PDFClass, SWFClass, ImageClass, Device; static ID id_doc; typedef struct doc_internal { + VALUE self; gfxsource_t*driver; // filled by alloc gfxdocument_t*doc; - gfxfontlist_t*list; + gfxfontlist_t*fontlist; } doc_internal_t; typedef struct page_internal { + doc_internal_t*doc; gfxpage_t*page; } page_internal_t; @@ -34,6 +36,11 @@ typedef struct glyph_internal { int nr; } glyph_internal_t; +typedef struct font_internal { + VALUE glyph_array; + gfxfont_t*font; +} font_internal_t; + static gfxsource_t* pdfdriver = 0; static gfxsource_t* imagedriver = 0; static gfxsource_t* swfdriver = 0; @@ -51,6 +58,7 @@ static VALUE doc_initialize(VALUE cls, VALUE _filename) Check_Type(_filename, T_STRING); Get_Doc(doc,cls); const char*filename = StringValuePtr(_filename); + doc->fontlist = gfxfontlist_create(); doc->doc = pdfdriver->open(pdfdriver, filename); return cls; } @@ -61,7 +69,6 @@ static VALUE doc_num_pages(VALUE cls) return INT2FIX(doc->doc->num_pages); } - static VALUE doc_get_page(VALUE cls, VALUE _nr) { Check_Type(_nr, T_FIXNUM); @@ -71,6 +78,7 @@ static VALUE doc_get_page(VALUE cls, VALUE _nr) VALUE v = page_allocate(DocumentPage); Get_Page(page,v) page->page = doc->doc->getpage(doc->doc, nr); + page->doc = doc; if(!page->page) { rb_raise(rb_eArgError, "No page %d in document", nr); return; @@ -86,6 +94,7 @@ static VALUE doc_each_page(VALUE cls) VALUE v = page_allocate(DocumentPage); Get_Page(page,v) page->page = doc->doc->getpage(doc->doc, t); + page->doc = doc; rb_yield(v); } return cls; @@ -93,11 +102,17 @@ static VALUE doc_each_page(VALUE cls) static void doc_mark(doc_internal_t*doc) { - // e.g. rb_gc_mark(z->page); + gfxfontlist_t*l = doc->fontlist; + while(l) { + if(l->user) + rb_gc_mark((VALUE)l->user); + l = l->next; + } } static void doc_free(doc_internal_t*doc) { + gfxfontlist_free(doc->fontlist, 0); doc->doc->destroy(doc->doc); free(doc); } @@ -105,7 +120,8 @@ static void doc_free(doc_internal_t*doc) static VALUE doc_allocate(VALUE cls, gfxsource_t*driver) { doc_internal_t*doc = 0; - VALUE v = Data_Make_Struct(cls, doc_internal_t, 0, doc_free, doc); + VALUE v = Data_Make_Struct(cls, doc_internal_t, doc_mark, doc_free, doc); + doc->self = v; memset(doc, 0, sizeof(doc_internal_t)); doc->driver = driver; return v; @@ -126,10 +142,14 @@ static void page_free(page_internal_t*page) } free(page); } +static void page_mark(page_internal_t*page) +{ + rb_gc_mark(page->doc->self); +} static VALUE page_allocate(VALUE cls) { page_internal_t*page = 0; - VALUE v = Data_Make_Struct(cls, page_internal_t, 0, page_free, page); + VALUE v = Data_Make_Struct(cls, page_internal_t, page_mark, page_free, page); memset(page, 0, sizeof(page_internal_t)); return v; } @@ -238,10 +258,44 @@ static VALUE glyph_unicode(VALUE cls) return INT2FIX(glyph->font->glyphs[glyph->nr].unicode); } +// ------------------------ font -------------------------------------------- + +#define Get_Font(font,cls) font_internal_t*font=0;Data_Get_Struct(cls, font_internal_t, font); + +static void font_mark(font_internal_t*font) +{ + rb_gc_mark(font->glyph_array); +} + +static void font_free(font_internal_t*font) +{ + free(font); +} + +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)); + return v; +} + +static VALUE font_name(VALUE cls) +{ + Get_Font(font,cls); + return rb_tainted_str_new2(font->font->id); +} + +static VALUE font_glyphs(VALUE cls) +{ + Get_Font(font,cls); + return font->glyph_array; +} + // ------------------------ gfx device -------------------------------------- typedef struct device_internal { - gfxfontlist_t*fontlist; + doc_internal_t*doc; VALUE v; } device_internal_t; @@ -280,21 +334,36 @@ VALUE convert_line(gfxline_t*line) gfxline_t*l = line; while(l) {l=l->next;len++;} - VALUE*a = malloc(sizeof(VALUE)*len); + VALUE array = rb_ary_new2(len); + rb_gc_register_address(&array); + int pos = 0; l = line; while(l) { + VALUE e; if(l->type == gfx_moveTo) { - a[pos] = rb_ary_new3(3, ID2SYM(id_move), rb_float_new(l->x), rb_float_new(l->y)); + e = rb_ary_new3(3, ID2SYM(id_move), Qfalse, Qfalse); + rb_ary_store(array, pos, e); + rb_ary_store(e, 1, rb_float_new(l->x)); + rb_ary_store(e, 2, rb_float_new(l->y)); } else if(l->type == gfx_lineTo) { - a[pos] = rb_ary_new3(3, ID2SYM(id_line), rb_float_new(l->x), rb_float_new(l->y)); + e = rb_ary_new3(3, ID2SYM(id_line), Qfalse, Qfalse); + rb_ary_store(array, pos, e); + rb_ary_store(e, 1, rb_float_new(l->x)); + rb_ary_store(e, 2, rb_float_new(l->y)); } else { - a[pos] = rb_ary_new3(5, ID2SYM(id_spline), rb_float_new(l->x), rb_float_new(l->y), rb_float_new(l->sx), rb_float_new(l->sy)); + e = rb_ary_new3(5, ID2SYM(id_spline), Qfalse, Qfalse, Qfalse, Qfalse); + rb_ary_store(array, pos, e); + rb_ary_store(e, 1, rb_float_new(l->x)); + rb_ary_store(e, 2, rb_float_new(l->y)); + rb_ary_store(e, 3, rb_float_new(l->sx)); + rb_ary_store(e, 4, rb_float_new(l->sy)); } pos++; l=l->next; } - return rb_ary_new4(len, a); + rb_gc_unregister_address(&array); + return array; } VALUE convert_color(gfxcolor_t*color) { @@ -302,14 +371,26 @@ VALUE convert_color(gfxcolor_t*color) } VALUE convert_matrix(gfxmatrix_t*matrix) { - return rb_ary_new3(3, - rb_ary_new3(2, rb_float_new(matrix->m00), rb_float_new(matrix->m01)), - rb_ary_new3(2, rb_float_new(matrix->m10), rb_float_new(matrix->m11)), - rb_ary_new3(2, rb_float_new(matrix->tx), rb_float_new(matrix->ty))); + VALUE array = rb_ary_new2(3); + rb_gc_register_address(&array); + 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)); + a = rb_ary_new2(2); + rb_ary_store(array, 1, a); + rb_ary_store(a, 0, rb_float_new(matrix->m10)); + rb_ary_store(a, 1, rb_float_new(matrix->m11)); + a = rb_ary_new2(2); + 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) { - VALUE v = (VALUE)gfxfontlist_getuserdata(i->fontlist, font->id); + VALUE v = (VALUE)gfxfontlist_getuserdata(i->doc->fontlist, font->id); if(v) return v; VALUE*a = (VALUE*)malloc(sizeof(VALUE)*font->num_glyphs); @@ -320,11 +401,14 @@ VALUE convert_font(device_internal_t*i, gfxfont_t*font) g->font = font; g->nr = t; } - v = rb_ary_new4(font->num_glyphs, a); - //rb_define_method(v, "id", font_get_id, 0); + VALUE v2 = font_allocate(Font); + Get_Font(f, v2); - i->fontlist = gfxfontlist_addfont2(i->fontlist, font, (void*)v); - return v; + 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 \ device_internal_t*i = (device_internal_t*)dev->internal; \ @@ -364,25 +448,66 @@ 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; - forward(v, id_stroke, 6, convert_line(line), rb_float_new(width), convert_color(color), ID2SYM(cap), ID2SYM(joint), rb_float_new(miterLimit)); + 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); + + 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 - forward(v, id_fill, 2, convert_line(line), convert_color(color)); + + VALUE v_line = convert_line(line); + rb_gc_register_address(&v_line); + VALUE v_color = convert_color(color); + rb_gc_register_address(&v_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 image = convert_image(img); - forward(v, id_fillbitmap, 4, convert_line(line), image, convert_matrix(matrix), Qnil); - invalidate_image(image); + 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); + 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) { HEAD ID typeid = (type == gfxgradient_linear)? id_linear : id_radial; - forward(v, id_fillgradient, 4, convert_line(line), convert_gradient(gradient), ID2SYM(typeid), convert_matrix(matrix)); + + 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); } void rb_addfont(gfxdevice_t*dev, gfxfont_t*font) { @@ -420,8 +545,8 @@ static VALUE page_render(VALUE cls, VALUE device) gfxdevice_t dev; device_internal_t i; - i.fontlist = gfxfontlist_create(); i.v = device; + i.doc = page->doc; dev.internal = &i; dev.setparameter = rb_setparameter; @@ -437,7 +562,7 @@ static VALUE page_render(VALUE cls, VALUE device) dev.drawlink = rb_drawlink; dev.endpage = rb_endpage; dev.finish = rb_finish; - + page->page->render(page->page, &dev); return cls; @@ -456,7 +581,6 @@ void Init_gfx() GFX = rb_define_module("GFX"); DocumentPage = rb_define_class_under(GFX, "DocumentPage", rb_cObject); - rb_define_alloc_func(DocumentPage, page_allocate); rb_define_method(DocumentPage, "width", page_width, 0); rb_define_method(DocumentPage, "height", page_height, 0); rb_define_method(DocumentPage, "nr", page_nr, 0); @@ -468,15 +592,17 @@ void Init_gfx() rb_define_method(Document, "each_page", doc_each_page, 0); Bitmap = rb_define_class_under(GFX, "Bitmap", rb_cObject); - rb_define_alloc_func(Bitmap, image_allocate); rb_define_method(Bitmap, "save_jpeg", image_save_jpeg, 2); Glyph = rb_define_class_under(GFX, "Glyph", rb_cObject); - rb_define_alloc_func(Glyph, glyph_allocate); rb_define_method(Glyph, "polygon", glyph_polygon, 0); rb_define_method(Glyph, "unicode", glyph_unicode, 0); rb_define_method(Glyph, "advance", glyph_advance, 0); + Font = rb_define_class_under(GFX, "Font", rb_cObject); + rb_define_method(Font, "name", font_name, 0); + rb_define_method(Font, "glyphs", font_glyphs, 0); + Device = rb_define_class_under(GFX, "Device", rb_cObject); rb_define_method(Device, "startpage", noop, -1); rb_define_method(Device, "endpage", noop, -1); diff --git a/lib/ruby/test.rb b/lib/ruby/test.rb index 40cbc5b..5e6b688 100644 --- a/lib/ruby/test.rb +++ b/lib/ruby/test.rb @@ -1,6 +1,7 @@ require 'gfx' -pdf = GFX::PDF.new('test.pdf') +#pdf = GFX::PDF.new('test.pdf') +pdf = GFX::PDF.new('/home/kramm/paper5.pdf') class TestRender < GFX::Device def startpage(width,height) @@ -13,33 +14,31 @@ class TestRender < GFX::Device puts "setparameter(#{key},#{value})" end def startclip(line) - puts "startclip(#{line})" + puts "startclip(#{line.inspect})" end def endclip() puts "endclip()" end def stroke(line, width, color, cap_style, joint_style, miterLimit) - puts "stroke(#{line}, #{width}, #{color}, #{cap_style}, #{joint_style}, #{miterLimit})" + puts "stroke(#{line.inspect}, #{width}, #{color.inspect}, #{cap_style}, #{joint_style}, #{miterLimit})" end def fill(line, color) - puts "fill(#{line}, #{color})" + puts "fill(#{line.inspect}, #{color.inspect})" end def fillbitmap(line, img, imgcoord2devcoord, cxform) - puts "fillbitmap(#{line}, #{img}, #{imgcoord2devcoord}, #{cxform})" + puts "fillbitmap(#{line.inspect}, #{img}, #{imgcoord2devcoord}, #{cxform})" end def fillgradient(dev, line, gradient, type, gradcoord2devcoord) - puts "fillgradient(#{line}, #{gradient}, #{type}, #{gradcoord2devcoord})" + puts "fillgradient(#{line.inspect}, #{gradient}, #{type}, #{gradcoord2devcoord})" end def addfont(font) - p @lastfont === font - @lastfont = font - puts "addfont(#{font})" + puts "addfont(#{font.name})" end def drawchar(font, glyph, color, matrix) - puts "drawchar(#{font}, #{glyph}, #{color}, #{matrix})" + puts "drawchar(#{font.name}, #{glyph}, #{color.inspect}, #{matrix.inspect})" end def drawlink(line, action) - puts "drawchar(#{line}, #{action})" + puts "drawchar(#{line.inspect}, #{action})" end end -- 1.7.10.4