--- parser3/src/classes/image.C 2003/11/07 13:59:21 1.97 +++ parser3/src/classes/image.C 2005/07/28 11:23:01 1.112 @@ -1,11 +1,11 @@ /** @file Parser: @b image parser class. - Copyright(c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com) + Copyright(c) 2001-2004 ArtLebedev Group (http://www.artlebedev.com) Author: Alexandr Petrosian (http://paf.design.ru) */ -static const char* IDENT_IMAGE_C="$Date: 2003/11/07 13:59:21 $"; +static const char * const IDENT_IMAGE_C="$Date: 2005/07/28 11:23:01 $"; /* jpegsize: gets the width and height (in pixels) of a jpeg file @@ -33,7 +33,7 @@ static const char* IDENT_IMAGE_C="$Date: class MImage: public Methoded { public: // VStateless_class - Value* create_new_value(Pool& apool) { return new VImage(); } + Value* create_new_value(Pool&, HashStringValue&) { return new VImage(); } public: MImage(); @@ -161,8 +161,6 @@ public: }; class Measure_file_reader: public Measure_reader { - - ; const String& file_name; const char* fname; int f; @@ -180,7 +178,7 @@ public: if(ssize_t(read_size)<0 || read_size>limit) throw Exception(0, &file_name, - "measure failed: actually read %lu bytes count not in [0..%lu] valid range", + "measure failed: actually read %u bytes count not in [0..%u] valid range", read_size, limit); return read_size; @@ -331,7 +329,7 @@ static void measure_gif(const String& or Measure_reader& reader, ushort& width, ushort& height) { const char* buf; - const int head_size=sizeof(GIF_Header); + const size_t head_size=sizeof(GIF_Header); if(reader.read(buf, head_size)=0) - return new VDate(t); + try { + return new VDate(cstr_to_time_t(cstr_writable)); + } + catch(...) { /*ignore bad date times*/ } } if(const char* premature_zero_pos=(const char* )memchr(cstr, 0, length)) @@ -637,7 +635,7 @@ static void measure_png(const String& or Measure_reader& reader, ushort& width, ushort& height) { const char* buf; - const int head_size=sizeof(PNG_Header); + const size_t head_size=sizeof(PNG_Header); if(reader.read(buf, head_size)(context); @@ -703,12 +701,12 @@ static void _measure(Request& r, MethodP ushort height=0; Value* exif=0; const String* file_name; - if(file_name=data.get_string()) { - File_measure_action_info info={0}; - info.width=&width; - info.height=&height; - info.exif=&exif; - info.file_name=file_name; + if((file_name=data.get_string())) { + File_measure_action_info info={ + &width, &height, + &exif, + file_name + }; file_read_action_under_lock(r.absolute(*file_name), "measure", file_measure_action, &info); } else { @@ -755,11 +753,10 @@ static void _html(Request& r, MethodPara if(params.count()) { // for backward compatibility: someday was ^html{} Value& vattribs=r.process_to_value(params[0], - /*0/*no name* /,*/ false/*don't intercept string*/); if(!vattribs.is_string()) // allow empty - if(attribs=vattribs.get_hash()) { - Attrib_info info={&tag}; + if((attribs=vattribs.get_hash())) { + Attrib_info info={&tag, 0}; attribs->for_each(append_attrib_pair, &info); } else throw Exception("parser.runtime", @@ -792,7 +789,6 @@ static gdImage* load(Request& r, throw Exception("file.missing", 0, "can not open '%s'", file_name_cstr); - return 0; } } @@ -817,17 +813,13 @@ static void _create(Request& r, MethodPa } static void _gif(Request& r, MethodParams& params) { - gdImage* image=GET_SELF(r, VImage).image; - if(!image) - throw Exception(0, - 0, - "does not contain an image"); + gdImage& image=GET_SELF(r, VImage).image(); const String *file_name=0; if(params.count()>0) file_name=¶ms.as_string(0, "file name must be string"); - gdBuf buf=image->Gif(); + gdBuf buf=image.Gif(); VFile& vfile=*new VFile; Value* content_type=new VString(*new String("image/gif")); @@ -840,77 +832,61 @@ static void _gif(Request& r, MethodParam } static void _line(Request& r, MethodParams& params) { - gdImage* image=GET_SELF(r, VImage).image; - if(!image) - throw Exception(0, - 0, - "does not contain an image"); + gdImage& image=GET_SELF(r, VImage).image(); - image->Line( + image.Line( params.as_int(0, "x0 must be int", r), params.as_int(1, "y0 must be int", r), params.as_int(2, "x1 must be int", r), params.as_int(3, "y1 must be int", r), - image->Color(params.as_int(4, "color must be int", r))); + image.Color(params.as_int(4, "color must be int", r))); } static void _fill(Request& r, MethodParams& params) { - gdImage* image=GET_SELF(r, VImage).image; - if(!image) - throw Exception(0, - 0, - "does not contain an image"); + gdImage& image=GET_SELF(r, VImage).image(); - image->Fill( + image.Fill( params.as_int(0, "x must be int", r), params.as_int(1, "y must be int", r), - image->Color(params.as_int(2, "color must be int", r))); + image.Color(params.as_int(2, "color must be int", r))); } static void _rectangle(Request& r, MethodParams& params) { - gdImage* image=GET_SELF(r, VImage).image; - if(!image) - throw Exception(0, - 0, - "does not contain an image"); + gdImage& image=GET_SELF(r, VImage).image(); - image->Rectangle( + image.Rectangle( params.as_int(0, "x0 must be int", r), params.as_int(1, "y0 must be int", r), params.as_int(2, "x1 must be int", r), params.as_int(3, "y1 must be int", r), - image->Color(params.as_int(4, "color must be int", r))); + image.Color(params.as_int(4, "color must be int", r))); } static void _bar(Request& r, MethodParams& params) { - gdImage* image=GET_SELF(r, VImage).image; - if(!image) - throw Exception(0, - 0, - "does not contain an image"); + gdImage& image=GET_SELF(r, VImage).image(); - image->FilledRectangle( + image.FilledRectangle( params.as_int(0, "x0 must be int", r), params.as_int(1, "y0 must be int", r), params.as_int(2, "x1 must be int", r), params.as_int(3, "y1 must be int", r), - image->Color(params.as_int(4, "color must be int", r))); + image.Color(params.as_int(4, "color must be int", r))); } #ifndef DOXYGEN static void add_point(Table::element_type row, gdImage::Point **p) { + if(row->count()!=2) + throw Exception(0, + 0, + "coordinates table must contain two columns: x and y values"); (**p).x=row->get(0)->as_int(); (**p).y=row->get(1)->as_int(); (*p)++; } #endif static void _replace(Request& r, MethodParams& params) { - gdImage* image=GET_SELF(r, VImage).image; - if(!image) - throw Exception(0, - 0, - "does not contain an image"); + gdImage& image=GET_SELF(r, VImage).image(); Table* table=params.as_no_junction(2, "coordinates must not be code").get_table(); if(!table) @@ -921,17 +897,13 @@ static void _replace(Request& r, MethodP gdImage::Point *all_p=new(PointerFreeGC) gdImage::Point[table->count()]; gdImage::Point *add_p=all_p; table->for_each(add_point, &add_p); - image->FilledPolygonReplaceColor(all_p, table->count(), - image->Color(params.as_int(0, "src color must be int", r)), - image->Color(params.as_int(1, "dest color must be int", r))); + image.FilledPolygonReplaceColor(all_p, table->count(), + image.Color(params.as_int(0, "src color must be int", r)), + image.Color(params.as_int(1, "dest color must be int", r))); } static void _polyline(Request& r, MethodParams& params) { - gdImage* image=GET_SELF(r, VImage).image; - if(!image) - throw Exception(0, - 0, - "does not contain an image"); + gdImage& image=GET_SELF(r, VImage).image(); Table* table=params.as_no_junction(1, "coordinates must not be code").get_table(); if(!table) @@ -942,17 +914,13 @@ static void _polyline(Request& r, Method gdImage::Point* all_p=new(PointerFreeGC) gdImage::Point[table->count()]; gdImage::Point *add_p=all_p; table->for_each(add_point, &add_p); - image->Polygon(all_p, table->count(), - image->Color(params.as_int(0, "color must be int", r)), + image.Polygon(all_p, table->count(), + image.Color(params.as_int(0, "color must be int", r)), false/*not closed*/); } static void _polygon(Request& r, MethodParams& params) { - gdImage* image=GET_SELF(r, VImage).image; - if(!image) - throw Exception(0, - 0, - "does not contain an image"); + gdImage& image=GET_SELF(r, VImage).image(); Table* table=params.as_no_junction(1, "coordinates must not be code").get_table(); if(!table) @@ -963,16 +931,12 @@ static void _polygon(Request& r, MethodP gdImage::Point* all_p=new(PointerFreeGC) gdImage::Point[table->count()]; gdImage::Point *add_p=all_p; table->for_each(add_point, &add_p); - image->Polygon(all_p, table->count(), - image->Color(params.as_int(0, "color must be int", r))); + image.Polygon(all_p, table->count(), + image.Color(params.as_int(0, "color must be int", r))); } static void _polybar(Request& r, MethodParams& params) { - gdImage* image=GET_SELF(r, VImage).image; - if(!image) - throw Exception(0, - 0, - "does not contain an image"); + gdImage& image=GET_SELF(r, VImage).image(); Table* table=params.as_no_junction(1, "coordinates must not be code").get_table(); if(!table) @@ -983,8 +947,8 @@ static void _polybar(Request& r, MethodP gdImage::Point* all_p=new(PointerFreeGC) gdImage::Point[table->count()]; gdImage::Point *add_p=all_p; table->for_each(add_point, &add_p); - image->FilledPolygon(all_p, table->count(), - image->Color(params.as_int(0, "color must be int", r))); + image.FilledPolygon(all_p, table->count(), + image.Color(params.as_int(0, "color must be int", r))); } // font @@ -998,9 +962,9 @@ const int Font::letter_spacing=1; Font::Font(//, const String& aalphabet, gdImage* aifont, int aheight, int amonospace, int aspacebarspace): - alphabet(aalphabet), height(aheight), monospace(amonospace), spacebarspace(aspacebarspace), - ifont(aifont) { + ifont(aifont), + alphabet(aalphabet) { } /* ******************************** char ********************************** */ @@ -1022,9 +986,9 @@ int Font::index_width(size_t index) { return 0; } -void Font::index_display(gdImage* image, int x, int y, size_t index){ +void Font::index_display(gdImage& image, int x, int y, size_t index){ if(index!=STRING_NOT_FOUND) - ifont->Copy(*image, x, y, 0, Y(0), index_width(index), height); + ifont->Copy(image, x, y, 0, Y(0), index_width(index), height); } /* ******************************** string ********************************** */ @@ -1042,7 +1006,7 @@ int Font::string_width(const String& s){ return result; } -void Font::string_display(gdImage* image, int x, int y, const String& s){ +void Font::string_display(gdImage& image, int x, int y, const String& s){ const char* cstr=s.cstr(); for(const char* current=cstr; *current; current++) { size_t index=index_of(*current); @@ -1077,10 +1041,10 @@ static void _font(Request& r, MethodPara "font-file height(%d) not divisable by alphabet size(%d), remainder=%d", image->SY(), alphabet.length(), remainder); - GET_SELF(r, VImage).font=new Font( + GET_SELF(r, VImage).set_font(new Font( alphabet, image, - image->SY() / alphabet.length(), monospace_width, spacebar_width); + image->SY() / alphabet.length(), monospace_width, spacebar_width)); } static void _text(Request& r, MethodParams& params) { @@ -1089,115 +1053,71 @@ static void _text(Request& r, MethodPara const String& s=params.as_string(2, "text must not be code"); VImage& vimage=GET_SELF(r, VImage); - if(vimage.image) - if(vimage.font) - vimage.font->string_display(vimage.image, x, y, s); - else - throw Exception("parser.runtime", - 0, - "set the font first"); - else - throw Exception(0, - 0, - "does not contain an image"); + vimage.font().string_display(vimage.image(), x, y, s); } static void _length(Request& r, MethodParams& params) { const String& s=params.as_string(0, "text must not be code"); VImage& vimage=GET_SELF(r, VImage); - if(vimage.image) - if(vimage.font) { - r.write_no_lang(*new VInt(vimage.font->string_width(s))); - } else - throw Exception("parser.runtime", - 0, - "set the font first"); - else - throw Exception(0, - 0, - "does not contain an image"); + r.write_no_lang(*new VInt(vimage.font().string_width(s))); } static void _arc(Request& r, MethodParams& params) { - gdImage* image=GET_SELF(r, VImage).image; - if(!image) - throw Exception(0, - 0, - "does not contain an image"); + gdImage& image=GET_SELF(r, VImage).image(); - image->Arc( + image.Arc( params.as_int(0, "center_x must be int", r), params.as_int(1, "center_y must be int", r), params.as_int(2, "width must be int", r), params.as_int(3, "height must be int", r), params.as_int(4, "start degrees must be int", r), params.as_int(5, "end degrees must be int", r), - image->Color(params.as_int(6, "cx must be int", r))); + image.Color(params.as_int(6, "cx must be int", r))); } static void _sector(Request& r, MethodParams& params) { - gdImage* image=GET_SELF(r, VImage).image; - if(!image) - throw Exception(0, - 0, - "does not contain an image"); + gdImage& image=GET_SELF(r, VImage).image(); - image->Sector( + image.Sector( params.as_int(0, "center_x must be int", r), params.as_int(1, "center_y must be int", r), params.as_int(2, "width must be int", r), params.as_int(3, "height must be int", r), params.as_int(4, "start degrees must be int", r), params.as_int(5, "end degrees must be int", r), - image->Color(params.as_int(6, "color must be int", r))); + image.Color(params.as_int(6, "color must be int", r))); } static void _circle(Request& r, MethodParams& params) { - gdImage* image=GET_SELF(r, VImage).image; - if(!image) - throw Exception(0, - 0, - "does not contain an image"); + gdImage& image=GET_SELF(r, VImage).image(); int size=params.as_int(2, "radius must be int", r)*2; - image->Arc( + image.Arc( params.as_int(0, "center_x must be int", r), params.as_int(1, "center_y must be int", r), size, //w size, //h 0, //s 360, //e - image->Color(params.as_int(3, "color must be int", r))); + image.Color(params.as_int(3, "color must be int", r))); } -gdImage* as_image(MethodParams& params, int index, const char* msg) { - gdImage* src=0; - +gdImage& as_image(MethodParams& params, int index, const char* msg) { Value& value=params.as_no_junction(index, msg); if(Value* vimage=value.as(VIMAGE_TYPE, false)) { - src=static_cast(vimage)->image; - if(!src) - throw Exception("parser.runtime", - 0, - msg); + return static_cast(vimage)->image(); } else throw Exception("parser.runtime", 0, msg); - - return src; } static void _copy(Request& r, MethodParams& params) { - gdImage* dest=GET_SELF(r, VImage).image; - if(!dest) - throw Exception(0, - 0, - "self does not contain an image"); + gdImage& dest=GET_SELF(r, VImage).image(); - gdImage* src=as_image(params, 0, "src must be image"); + gdImage& src=as_image(params, 0, "src must be image"); int sx=params.as_int(1, "src_x must be int", r); int sy=params.as_int(2, "src_y must be int", r); @@ -1212,9 +1132,22 @@ static void _copy(Request& r, MethodPara int tolerance=params.count()>1+2+2+2+2? params.as_int(1+2+2+2+2, "tolerance must be int", r):150; - src->CopyResampled(*dest, dx, dy, sx, sy, dw, dh, sw, sh, tolerance); + src.CopyResampled(dest, dx, dy, sx, sy, dw, dh, sw, sh, tolerance); } else - src->Copy(*dest, dx, dy, sx, sy, sw, sh); + src.Copy(dest, dx, dy, sx, sy, sw, sh); +} + +static void _pixel(Request& r, MethodParams& params) { + gdImage& image=GET_SELF(r, VImage).image(); + + int x=params.as_int(0, "x must be int", r); + int y=params.as_int(1, "y must be int", r); + + if(params.count()>2) { + image.SetPixel(x, y, + image.Color(params.as_int(2, "color must be int", r))); + } else + r.write_no_lang(*new VInt(image.DecodeColor(image.GetPixel(x, y)))); } @@ -1283,4 +1216,7 @@ MImage::MImage(): Methoded("image") { // ^image.copy[source](src x;src y;src w;src h;dst x;dst y[;dest w[;dest h[;tolerance]]]) add_native_method("copy", Method::CT_DYNAMIC, _copy, 1+2+2+2, (1+2+2+2)+2+1); + + // ^image.pixel(x;y)[(color)] + add_native_method("pixel", Method::CT_DYNAMIC, _pixel, 2, 3); }