/* Method: Magick::colors [ { |colorinfo| } ] Purpose: If called with the optional block, iterates over the colors, otherwise returns an array of Magick::Color objects Notes: There are 3 implementations */ VALUE Magick_colors(VALUE class) { #if defined(HAVE_GETCOLORINFOARRAY) // GraphicsMagick ColorInfo **color_ary; ExceptionInfo exception; volatile VALUE ary; int x; GetExceptionInfo(&exception); color_ary = GetColorInfoArray(&exception); HANDLE_ERROR if (rb_block_given_p()) { x = 0; while(color_ary[x]) { rb_yield(Color_from_ColorInfo(color_ary[x])); x += 1; } magick_free(color_ary); return class; } else { ary = rb_ary_new(); x = 0; while (color_ary[x]) { rb_ary_push(ary, Color_from_ColorInfo(color_ary[x])); x += 1; } magick_free(color_ary); return ary; } #elif defined(HAVE_GETCOLORINFOLIST) // ImageMagick 6.0.0 const ColorInfo **color_info_list; unsigned long number_colors, x; volatile VALUE ary; #if defined(HAVE_OLD_GETCOLORINFOLIST) color_info_list = GetColorInfoList("*", &number_colors); #else // IM 6.1.3 added an exception parm to GetColorInfoList ExceptionInfo exception; GetExceptionInfo(&exception); color_info_list = GetColorInfoList("*", &number_colors, &exception); HANDLE_ERROR #endif if (rb_block_given_p()) { for(x = 0; x < number_colors; x++) { rb_yield(Color_from_ColorInfo(color_info_list[x])); } magick_free(color_info_list); return class; } else { ary = rb_ary_new2((long) number_colors); for(x = 0; x < number_colors; x++) { rb_ary_push(ary, Color_from_ColorInfo(color_info_list[x])); } magick_free(color_info_list); return ary; } #else // ImageMagick < 6.0.0 const ColorInfo *color_list; ColorInfo *color; ExceptionInfo exception; volatile VALUE ary, el; GetExceptionInfo(&exception); color_list = GetColorInfo("*", &exception); DestroyExceptionInfo(&exception); // The order of the colors list can change in mid-iteration, // so the only way we can guarantee a single pass thru the list // is to copy the elements into an array without returning to // IM. So, we always create a Ruby array and either return it // or iterate over it. ary = rb_ary_new(); for (color = (ColorInfo *)color_list; color; color = color->next) { rb_ary_push(ary, Color_from_ColorInfo(color)); } // If block, iterate over colors if (rb_block_given_p()) { while ((el = rb_ary_shift(ary)) != Qnil) { rb_yield(el); } return class; } else { return ary; } #endif }