/* Method: Draw#marshal_load Purpose: Support Marsal.load Notes: On entry all fields are all-bits-0 */ VALUE Draw_marshal_load(VALUE self, VALUE ddraw) { Draw *draw; Pixel *pixel; volatile VALUE val; Data_Get_Struct(self, Draw, draw); draw->info = magick_malloc(sizeof(DrawInfo)); if (!draw->info) { rb_raise(rb_eNoMemError, "not enough memory to continue"); } GetDrawInfo(NULL, draw->info); OBJ_TO_MAGICK_STRING(draw->info->geometry, rb_hash_aref(ddraw, CSTR2SYM("geometry"))); //val = rb_hash_aref(ddraw, CSTR2SYM("viewbox")); //Export_RectangleInfo(&draw->info->viewbox, val); val = rb_hash_aref(ddraw, CSTR2SYM("affine")); Export_AffineMatrix(&draw->info->affine, val); draw->info->gravity = (GravityType) FIX2INT(rb_hash_aref(ddraw, CSTR2SYM("gravity"))); val = rb_hash_aref(ddraw, CSTR2SYM("fill")); Data_Get_Struct(val, Pixel, pixel); draw->info->fill = *pixel; val = rb_hash_aref(ddraw, CSTR2SYM("stroke")); Data_Get_Struct(val, Pixel, pixel); draw->info->stroke = *pixel; draw->info->stroke_width = NUM2DBL(rb_hash_aref(ddraw, CSTR2SYM("stroke_width"))); draw->info->fill_pattern = str_to_image(rb_hash_aref(ddraw, CSTR2SYM("fill_pattern"))); draw->info->stroke_pattern = str_to_image(rb_hash_aref(ddraw, CSTR2SYM("stroke_pattern"))); draw->info->stroke_antialias = RTEST(rb_hash_aref(ddraw, CSTR2SYM("stroke_antialias"))); draw->info->text_antialias = RTEST(rb_hash_aref(ddraw, CSTR2SYM("text_antialias"))); draw->info->decorate = (DecorationType) FIX2INT(rb_hash_aref(ddraw, CSTR2SYM("decorate"))); OBJ_TO_MAGICK_STRING(draw->info->font, rb_hash_aref(ddraw, CSTR2SYM("font"))); OBJ_TO_MAGICK_STRING(draw->info->family, rb_hash_aref(ddraw, CSTR2SYM("family"))); draw->info->style = (StyleType) FIX2INT(rb_hash_aref(ddraw, CSTR2SYM("style"))); draw->info->stretch = (StretchType) FIX2INT(rb_hash_aref(ddraw, CSTR2SYM("stretch"))); draw->info->weight = NUM2ULONG(rb_hash_aref(ddraw, CSTR2SYM("weight"))); OBJ_TO_MAGICK_STRING(draw->info->encoding, rb_hash_aref(ddraw, CSTR2SYM("encoding"))); draw->info->pointsize = NUM2DBL(rb_hash_aref(ddraw, CSTR2SYM("pointsize"))); OBJ_TO_MAGICK_STRING(draw->info->density, rb_hash_aref(ddraw, CSTR2SYM("density"))); draw->info->align = (AlignType) FIX2INT(rb_hash_aref(ddraw, CSTR2SYM("align"))); val = rb_hash_aref(ddraw, CSTR2SYM("undercolor")); Data_Get_Struct(val, Pixel, pixel); draw->info->undercolor = *pixel; draw->info->clip_units = FIX2INT(rb_hash_aref(ddraw, CSTR2SYM("clip_units"))); draw->info->opacity = NUM2QUANTUM(rb_hash_aref(ddraw, CSTR2SYM("opacity"))); #if defined(HAVE_ST_KERNING) draw->info->kerning = NUM2DBL(rb_hash_aref(ddraw, CSTR2SYM("kerning"))); #endif #if defined(HAVE_ST_INTERWORD_SPACING) draw->info->interword_spacing = NUM2DBL(rb_hash_aref(ddraw, CSTR2SYM("interword_spacing"))); #endif draw->primitives = rb_hash_aref(ddraw, CSTR2SYM("primitives")); return self; }
/* Method: Draw#composite(x,y,width,height,img,operator=OverCompositeOp) Purpose: Implement the "image" drawing primitive Notes: The "img" argument can be either an ImageList object or an Image argument. */ VALUE Draw_composite(int argc, VALUE *argv, VALUE self) { Draw *draw; const char *op = "Over"; double x, y, width, height; CompositeOperator cop = OverCompositeOp; volatile VALUE image; Image *comp_img; struct TmpFile_Name *tmpfile_name; char name[MaxTextExtent]; // Buffer for "image" primitive char primitive[MaxTextExtent]; if (argc < 5 || argc > 6) { rb_raise(rb_eArgError, "wrong number of arguments (%d for 5 or 6)", argc); } // Retrieve the image to composite image = rm_cur_image(argv[4]); (void) rm_check_destroyed(image); x = NUM2DBL(argv[0]); y = NUM2DBL(argv[1]); width = NUM2DBL(argv[2]); height = NUM2DBL(argv[3]); // The default composition operator is "Over". if (argc == 6) { VALUE_TO_ENUM(argv[5], cop, CompositeOperator); switch (cop) { case AddCompositeOp: op = "Add"; break; case AtopCompositeOp: op = "Atop"; break; case BumpmapCompositeOp: op = "Bumpmap"; break; case ClearCompositeOp: op = "Clear"; break; case CopyBlueCompositeOp: op = "CopyBlue"; break; case CopyGreenCompositeOp: op = "CopyGreen"; break; case CopyOpacityCompositeOp: op = "CopyOpacity"; break; case CopyRedCompositeOp: op = "CopyRed"; break; case CopyCompositeOp: op = "Copy"; break; case DifferenceCompositeOp: op = "Difference"; break; case InCompositeOp: op = "In"; break; case MinusCompositeOp: op = "Minus"; break; case MultiplyCompositeOp: op = "Multiply"; break; case OutCompositeOp: op = "Out"; break; case OverCompositeOp: op = "Over"; break; case PlusCompositeOp: op = "Plus"; break; case SubtractCompositeOp: op = "Subtract"; break; case XorCompositeOp: op = "Xor"; break; default: rb_raise(rb_eArgError, "unknown composite operator (%d)", cop); break; } } Data_Get_Struct(self, Draw, draw); // Create a temp copy of the composite image Data_Get_Struct(image, Image, comp_img); rm_write_temp_image(comp_img, name); // Add the temp filename to the filename array. // Use Magick storage since we need to keep the list around // until destroy_Draw is called. tmpfile_name = magick_malloc(sizeof(struct TmpFile_Name)+strlen(name)); strcpy(tmpfile_name->name, name); tmpfile_name->next = draw->tmpfile_ary; draw->tmpfile_ary = tmpfile_name; // Form the drawing primitive (void) sprintf(primitive, "image %s %g,%g,%g,%g '%s'", op, x, y, width, height, name); // Send "primitive" to self. (void) rb_funcall(self, rb_intern("primitive"), 1, rb_str_new2(primitive)); return self; }
/** * Implement the "image" drawing primitive. * * Ruby usage: * - @verbatim Draw#composite(x,y,width,height,img) @endverbatim * - @verbatim Draw#composite(x,y,width,height,img,operator) @endverbatim * * Notes: * - Default operator is overComposite * - The "img" argument can be either an ImageList object or an Image * argument. * * @param argc number of input arguments * @param argv array of input arguments * @param self this object * @return self */ VALUE Draw_composite(int argc, VALUE *argv, VALUE self) { Draw *draw; const char *op; double x, y, width, height; CompositeOperator cop; VALUE image; Image *comp_img; struct TmpFile_Name *tmpfile_name; char name[MaxTextExtent]; // Buffer for "image" primitive char primitive[MaxTextExtent]; if (argc < 5 || argc > 6) { rb_raise(rb_eArgError, "wrong number of arguments (%d for 5 or 6)", argc); } // Retrieve the image to composite image = rm_cur_image(argv[4]); comp_img = rm_check_destroyed(image); x = NUM2DBL(argv[0]); y = NUM2DBL(argv[1]); width = NUM2DBL(argv[2]); height = NUM2DBL(argv[3]); cop = OverCompositeOp; if (argc == 6) { VALUE_TO_ENUM(argv[5], cop, CompositeOperator); } op = CommandOptionToMnemonic(MagickComposeOptions, cop); if (rm_strcasecmp("Unrecognized", op) == 0) { rb_raise(rb_eArgError, "unknown composite operator (%d)", cop); } Data_Get_Struct(self, Draw, draw); // Create a temp copy of the composite image rm_write_temp_image(comp_img, name); // Add the temp filename to the filename array. // Use Magick storage since we need to keep the list around // until destroy_Draw is called. tmpfile_name = magick_malloc(sizeof(struct TmpFile_Name)+strlen(name)); strcpy(tmpfile_name->name, name); tmpfile_name->next = draw->tmpfile_ary; draw->tmpfile_ary = tmpfile_name; // Form the drawing primitive (void) snprintf(primitive, sizeof(primitive), "image %s %g,%g,%g,%g '%s'", op, x, y, width, height, name); // Send "primitive" to self. (void) rb_funcall(self, rb_intern("primitive"), 1, rb_str_new2(primitive)); RB_GC_GUARD(image); return self; }