--- parser3/src/classes/image.C 2003/02/06 15:33:14 1.90.2.7 +++ parser3/src/classes/image.C 2003/11/07 13:59:21 1.97 @@ -5,7 +5,7 @@ Author: Alexandr Petrosian (http://paf.design.ru) */ -static const char* IDENT_IMAGE_C="$Date: 2003/02/06 15:33:14 $"; +static const char* IDENT_IMAGE_C="$Date: 2003/11/07 13:59:21 $"; /* jpegsize: gets the width and height (in pixels) of a jpeg file @@ -31,9 +31,9 @@ static const char* IDENT_IMAGE_C="$Date: // class -class MImage : public Methoded { +class MImage: public Methoded { public: // VStateless_class - ValuePtr create_new_value() { return ValuePtr(new VImage()); } + Value* create_new_value(Pool& apool) { return new VImage(); } public: MImage(); @@ -45,17 +45,17 @@ public: // Methoded // globals -MethodedPtr image_class(new MImage); +DECLARE_CLASS_VAR(image, new MImage, 0); // helpers /// value of exif tag -> it's value -class EXIF_tag_value2name: public Hash { +class EXIF_tag_value2name: public Hash { public: EXIF_tag_value2name() { // image JPEG Exif #define EXIF_TAG(tag, name) \ - exif_tag_value2name.put(tag, #name); + put(tag, #name); // Tags used by IFD0 (main image) EXIF_TAG(0x010e, ImageDescription); EXIF_TAG(0x010f, Make); @@ -155,31 +155,31 @@ public: #ifndef DOXYGEN class Measure_reader { public: - virtual size_t read(const char *&buf, size_t limit)=0; + virtual size_t read(const char* &buf, size_t limit)=0; virtual void seek(long value, int whence)=0; virtual long tell()=0; }; class Measure_file_reader: public Measure_reader { - Pool& pool; - StringPtr file_name; const char* fname; + ; + const String& file_name; const char* fname; int f; public: - Measure_file_reader(Pool& apool, int af, StringPtr afile_name, const char* afname): - pool(apool), file_name(afile_name), fname(afname), f(af) { + Measure_file_reader(int af, const String& afile_name, const char* afname): + file_name(afile_name), fname(afname), f(af) { } - override size_t read(const char *&abuf, size_t limit) { + override size_t read(const char* &abuf, size_t limit) { if(limit==0) return 0; - char* lbuf=new(pool) char[limit]; + char* lbuf=new(PointerFreeGC) char[limit]; size_t read_size=(size_t)::read(f, lbuf, limit); abuf=lbuf; if(ssize_t(read_size)<0 || read_size>limit) throw Exception(0, - file_name, + &file_name, "measure failed: actually read %lu bytes count not in [0..%lu] valid range", read_size, limit); @@ -189,7 +189,7 @@ public: override void seek(long value, int whence) { if(lseek(f, value, whence)<0) throw Exception("image.format", - file_name, + &file_name, "seek(value=%ld, whence=%d) failed: %s (%d), actual filename '%s'", value, whence, strerror(errno), errno, fname); } @@ -201,16 +201,16 @@ public: class Measure_buf_reader: public Measure_reader { const char* buf; size_t size; - StringPtr file_name; + const String& file_name; size_t offset; public: - Measure_buf_reader(const char* abuf, size_t asize, StringPtr afile_name): + Measure_buf_reader(const char* abuf, size_t asize, const String& afile_name): buf(abuf), size(asize), file_name(afile_name), offset(0) { } - override size_t read(const char *&abuf, size_t limit) { + override size_t read(const char* &abuf, size_t limit) { size_t to_read=min(limit, size-offset); abuf=buf+offset; offset+=to_read; @@ -223,15 +223,15 @@ public: case SEEK_CUR: new_offset=offset+value; break; case SEEK_SET: new_offset=(size_t)value; break; default: - throw Exception(Exception::undefined_type, - Exception::undefined_source, + throw Exception(0, + 0, "whence #%d not supported", 0, whence); break; // never } if((ssize_t)new_offset<0 || new_offset>size) throw Exception("image.format", - file_name, + &file_name, "seek(value=%l, whence=%d) failed: out of buffer, new_offset>size (%l>%l) or new_offset<0", value, whence, new_offset, size); offset=new_offset; @@ -279,7 +279,7 @@ struct JPG_Size_segment_body { }; /// JPEG frame header -struct JPG_Exif_segment_start { +struct JPG_Exif_segment_begin { char signature[6]; // Exif\0\0 }; @@ -291,7 +291,7 @@ struct JPG_Exif_TIFF_header { }; // JPEG Exif IFD start -struct JPG_Exif_IFD_start { +struct JPG_Exif_IFD_begin { uchar directory_entry_count[2]; // the number of directory entry contains in this IFD }; @@ -327,60 +327,60 @@ inline uint endian_to_uint(bool is_big, x_endian_to_uint(b[0], b[1], b[2], b[3]); } -static void measure_gif(Pool& pool, StringPtr origin_string, +static void measure_gif(const String& origin_string, Measure_reader& reader, ushort& width, ushort& height) { - const char *buf; + const char* buf; const int head_size=sizeof(GIF_Header); if(reader.read(buf, head_size)signature, "GIF", 3)!=0) throw Exception("image.format", - origin_string, + &origin_string, "not GIF file - wrong signature"); width=endian_to_ushort(false, head->width); height=endian_to_ushort(false, head->height); } -static ValuePtr parse_IFD_entry_formatted_one_value(Pool& pool, +static Value* parse_IFD_entry_formatted_one_value( bool is_big, ushort format, size_t component_size, const uchar *value) { switch(format) { case 1: // unsigned byte - return ValuePtr(new VInt((uchar)value[0])); + return new VInt((uchar)value[0]); case 3: // unsigned short - return ValuePtr(new VInt(endian_to_ushort(is_big, value))); + return new VInt(endian_to_ushort(is_big, value)); case 4: // unsigned long // 'double' because parser's Int is signed - return ValuePtr(new VDouble(endian_to_uint(is_big, value))); + return new VDouble(endian_to_uint(is_big, value)); case 5: // unsigned rational { uint numerator=endian_to_uint(is_big, value); value+=component_size/2; uint denominator=endian_to_uint(is_big, value); if(!denominator) - return ValuePtr(0); - return ValuePtr(new VDouble(((double)numerator)/denominator)); + return 0; + return new VDouble(((double)numerator)/denominator); } case 6: // signed byte - return ValuePtr(new VInt((signed char)value[0])); + return new VInt((signed char)value[0]); case 8: // signed short - return ValuePtr(new VInt((signed short)endian_to_ushort(is_big, value))); + return new VInt((signed short)endian_to_ushort(is_big, value)); case 9: // signed long - return ValuePtr(new VInt((signed int)endian_to_uint(is_big, value))); + return new VInt((signed int)endian_to_uint(is_big, value)); case 10: // signed rational { signed int numerator=(signed int)endian_to_uint(is_big, value); value+=component_size/2; uint denominator=endian_to_uint(is_big, value); if(!denominator) - return ValuePtr(0); - return ValuePtr(new VDouble(numerator/denominator)); + return 0; + return new VDouble(numerator/denominator); } /* case 11: // single float @@ -390,52 +390,51 @@ static ValuePtr parse_IFD_entry_formatte */ }; - return ValuePtr(0); + return 0; } // date.C -time_t cstr_to_time_t(char *cstr, const String *report_error_origin); +time_t cstr_to_time_t(char *cstr, bool fail_on_error); -static ValuePtr parse_IFD_entry_formatted_value(Pool& pool, - bool is_big, ushort format, - size_t component_size, uint components_count, - const uchar *value) { +static Value* parse_IFD_entry_formatted_value(bool is_big, ushort format, + size_t component_size, uint components_count, + const uchar *value) { if(format==2) { // ascii string, exception: the only type with varying size const char* cstr=(const char* )value; - size_t size=components_count; + size_t length=components_count; // Data format is "YYYY:MM:DD HH:MM:SS"+0x00, total 20bytes - if(size==JPEG_EXIF_DATE_CHARS + if(length==JPEG_EXIF_DATE_CHARS && isdigit(cstr[0]) - && cstr[JPEG_EXIF_DATE_CHARS-1]==0) { + && cstr[length-1]==0) { char cstr_writable[JPEG_EXIF_DATE_CHARS]; strcpy(cstr_writable, cstr); - time_t t=cstr_to_time_t(cstr_writable, 0/* do not throw exception, just return bad result */); + time_t t=cstr_to_time_t(cstr_writable, + false/* do not throw exception, just return bad result */); if(t>=0) - return ValuePtr(new VDate(t)); + return new VDate(t); } - if(const char* premature_zero_pos=(const char* )memchr(cstr, 0, size)) - size=premature_zero_pos-cstr; - return ValuePtr(new VString(StringPtr(new String(cstr, size, true/*tainted*/)))); + if(const char* premature_zero_pos=(const char* )memchr(cstr, 0, length)) + length=premature_zero_pos-cstr; + return new VString(*new String(cstr, length, true/*tainted*/)); } if(components_count==1) - return parse_IFD_entry_formatted_one_value(pool, is_big, format, component_size, value); + return parse_IFD_entry_formatted_one_value(is_big, format, component_size, value); - VHashPtr result(new VHash); - HashStringValue& hash=result->hash(Exception::undefined_source); + VHash* result=new VHash; + HashStringValue& hash=result->hash(); for(uint i=0; idirectory_entry_count); for(int i=0; isignature, "Exif\0\0", 4+2)!=0) //signature invalid? return 0; // ignore invalid block @@ -563,16 +557,16 @@ static ValuePtr parse_exif(Pool& pool, uint first_IFD_offset=endian_to_uint(is_big, head->first_IFD_offset); reader.seek(tiff_base+first_IFD_offset, SEEK_SET); - VHashPtr vhash(new VHash); + VHash* vhash=new VHash; // IFD - parse_IFD(pool, vhash->hash(Exception::undefined_source), is_big, reader, tiff_base); + parse_IFD(vhash->hash(), is_big, reader, tiff_base); return vhash; } -static void measure_jpeg(Pool& pool, StringPtr origin_string, - Measure_reader& reader, ushort& width, ushort& height, ValuePtr* exif) { +static void measure_jpeg(const String& origin_string, + Measure_reader& reader, ushort& width, ushort& height, Value** exif) { // JFIF format markers const uchar MARKER=0xFF; const uchar CODE_SIZE_A=0xC0; @@ -581,17 +575,17 @@ static void measure_jpeg(Pool& pool, Str const uchar CODE_SIZE_D=0xC3; const uchar CODE_EXIF=0xE1; - const char *buf; + const char* buf; const size_t prefix_size=2; if(reader.read(buf, prefix_size)marker!=MARKER) throw Exception("image.format", - origin_string, + &origin_string, "not JPEG file - marker not found"); switch(head->code) { // http://www.ba.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html case CODE_EXIF: if(exif && !*exif) // seen .jpg with some xml under EXIF tag, after real exif block :) - *exif=parse_exif(pool, reader, origin_string); + *exif=parse_exif(reader, origin_string); break; case CODE_SIZE_A: @@ -621,7 +615,7 @@ static void measure_jpeg(Pool& pool, Str // Segments that contain size info if(reader.read(buf, sizeof(JPG_Size_segment_body))signature, "IHDR", 4)!=0) throw Exception("image.format", - origin_string, + &origin_string, "not PNG file - wrong signature"); width=endian_to_ushort(true, head->width); @@ -661,24 +655,24 @@ static void measure_png(Pool& pool, Stri // measure center -static void measure(Pool& pool, StringPtr file_name, - Measure_reader& reader, ushort& width, ushort& height, ValuePtr* exif) { - CharPtr file_name_cstr=file_name->cstr(String::UL_FILE_SPEC); +static void measure(const String& file_name, + Measure_reader& reader, ushort& width, ushort& height, Value** exif) { + const char* file_name_cstr=file_name.cstr(String::L_FILE_SPEC); if(const char* cext=strrchr(file_name_cstr, '.')) { cext++; if(strcasecmp(cext, "GIF")==0) - measure_gif(pool, file_name, reader, width, height); + measure_gif(file_name, reader, width, height); else if(strcasecmp(cext, "JPG")==0 || strcasecmp(cext, "JPEG")==0) - measure_jpeg(pool, file_name, reader, width, height, exif); + measure_jpeg(file_name, reader, width, height, exif); else if(strcasecmp(cext, "PNG")==0) - measure_png(pool, file_name, reader, width, height); + measure_png(file_name, reader, width, height); else throw Exception("image.format", - file_name, + &file_name, "unhandled image file name extension '%s'", cext); } else throw Exception("image.format", - file_name, + &file_name, "can not determine image type - no file name extension"); } @@ -688,73 +682,69 @@ static void measure(Pool& pool, StringPt struct File_measure_action_info { ushort* width; ushort* height; - ValuePtr* exif; - StringPtr file_name; + Value** exif; + const String* file_name; }; #endif -static void file_measure_action(Pool& pool, +static void file_measure_action( struct stat& finfo, int f, - StringPtr file_spec, const char* fname, bool as_text, + const String& file_spec, const char* fname, bool as_text, void *context) { File_measure_action_info& info=*static_cast(context); - Measure_file_reader reader(pool, f, info.file_name, fname); - measure(pool, info.file_name, reader, *info.width, *info.height, info.exif); + Measure_file_reader reader(f, *info.file_name, fname); + measure(*info.file_name, reader, *info.width, *info.height, info.exif); } -static void _measure(Request& r, StringPtr method_name, MethodParams& params) { - Pool& pool=r.pool(); - - ValuePtr data=params.as_no_junction(0, "data must not be code"); +static void _measure(Request& r, MethodParams& params) { + Value& data=params.as_no_junction(0, "data must not be code"); ushort width=0; ushort height=0; - ValuePtr exif(0); - StringPtr file_name; - if(file_name=data->get_string(&pool)) { - File_measure_action_info info; + 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; - file_read_action_under_lock(pool, r.absolute(file_name), + file_read_action_under_lock(r.absolute(*file_name), "measure", file_measure_action, &info); } else { - VFilePtr vfile=data->as_vfile(pool); - file_name=vfile->fields().get(name_name)->as_string(&pool); + VFile* vfile=data.as_vfile(); + file_name=&vfile->fields().get(name_name)->as_string(); Measure_buf_reader reader( vfile->value_ptr(), vfile->value_size(), - file_name + *file_name ); - measure(pool, file_name, reader, width, height, &exif); + measure(*file_name, reader, width, height, &exif); } - GET_SELF(r, VImage).set(file_name, width, height, gdImagePtr(0), exif); + GET_SELF(r, VImage).set(file_name, width, height, 0, exif); } #ifndef DOXYGEN struct Attrib_info { - Pool* pool; String* tag; ///< html tag being constructed HashStringValue* skip; ///< tag attributes not to append to tag string [to skip] }; #endif static void append_attrib_pair( - HashStringValue::key_type key, - HashStringValue::value_type value, - Attrib_info* info) { + HashStringValue::key_type key, + HashStringValue::value_type value, + Attrib_info* info) { // skip user-specified and internal(starting with "line-") attributes - if(info->skip && info->skip->get(key) || key->pos("line-")==0) + if(info->skip && info->skip->get(key) || key.pos("line-")==0) return; // src="a.gif" width=123 ismap[=-1] *info->tag << " " << key; if(value->is_string() || value->as_int()>=0) - *info->tag << "=\"" << value->as_string(info->pool) << "\""; + *info->tag << "=\"" << value->as_string() << "\""; } -static void _html(Request& r, StringPtr method_name, MethodParams& params) { - Pool& pool=r.pool(); +static void _html(Request& r, MethodParams& params) { String tag; tag << "is_string()) // allow empty - if(attribs=vattribs->get_hash(method_name)) { - Attrib_info info={&pool, &tag}; + if(!vattribs.is_string()) // allow empty + if(attribs=vattribs.get_hash()) { + Attrib_info info={&tag}; attribs->for_each(append_attrib_pair, &info); } else throw Exception("parser.runtime", - method_name, + 0, "attributes must be hash"); } { - Attrib_info info={&pool, &tag, attribs}; + Attrib_info info={&tag, attribs}; fields.for_each(append_attrib_pair, &info); } tag << " />"; @@ -786,80 +776,74 @@ static void _html(Request& r, StringPtr } /// @test wrap FILE to auto-object -static gdImagePtr load(Request& r, StringPtr method_name, - StringPtr file_name){ - Pool& pool=r.pool(); - - CharPtr file_name_cstr=r.absolute(file_name)->cstr(String::UL_FILE_SPEC); +static gdImage* load(Request& r, + const String& file_name){ + const char* file_name_cstr=r.absolute(file_name).cstr(String::L_FILE_SPEC); if(FILE *f=fopen(file_name_cstr, "rb")) { - gdImagePtr image(new gdImage); + gdImage* image=new gdImage; bool ok=image->CreateFromGif(f); fclose(f); if(!ok) throw Exception("image.format", - file_name, + &file_name, "is not in GIF format"); return image; } else { throw Exception("file.missing", - method_name, + 0, "can not open '%s'", file_name_cstr); - return gdImagePtr(0); + return 0; } } -static void _load(Request& r, StringPtr method_name, MethodParams& params) { - Pool& pool=r.pool(); +static void _load(Request& r, MethodParams& params) { + const String& file_name=params.as_string(0, "file name must not be code"); - StringPtr file_name=params.as_string(0, "file name must not be code"); - - gdImagePtr image=load(r, method_name, file_name); - GET_SELF(r, VImage).set(file_name, image->SX(), image->SY(), image); + gdImage* image=load(r, file_name); + GET_SELF(r, VImage).set(&file_name, image->SX(), image->SY(), image); } -static void _create(Request& r, StringPtr method_name, MethodParams& params) { - Pool& pool=r.pool(); - +static void _create(Request& r, MethodParams& params) { int width=params.as_int(0, "width must be int", r); int height=params.as_int(1, "height must be int", r); int bgcolor_value=0xffFFff; if(params.count()>2) bgcolor_value=params.as_int(2, "color must be int", r); - gdImagePtr image(new gdImage); + gdImage* image=new gdImage; image->Create(width, height); image->FilledRectangle(0, 0, width-1, height-1, image->Color(bgcolor_value)); - GET_SELF(r, VImage).set(StringPtr(0), width, height, image); + GET_SELF(r, VImage).set(0, width, height, image); } -static void _gif(Request& r, StringPtr method_name, MethodParams& params) { - Pool& pool=r.pool(); - - gdImagePtr image=GET_SELF(r, VImage).image; +static void _gif(Request& r, MethodParams& params) { + gdImage* image=GET_SELF(r, VImage).image; if(!image) throw Exception(0, - method_name, + 0, "does not contain an image"); - // could _ but don't thing it's wise to use $image.src for vfile.name + const String *file_name=0; + if(params.count()>0) + file_name=¶ms.as_string(0, "file name must be string"); - String out; image->Gif(pool, out); + gdBuf buf=image->Gif(); - VFilePtr vfile(new VFile); - ValuePtr content_type(new VString(StringPtr(new String("image/gif")))); - vfile->set(pool, false/*not tainted*/, - out.cstr(), out.size(), 0, content_type); + VFile& vfile=*new VFile; + Value* content_type=new VString(*new String("image/gif")); + vfile.set(false/*not tainted*/, + (const char*)buf.ptr, buf.size, + file_name? file_name->cstr(String::L_FILE_SPEC): 0, + content_type); r.write_no_lang(vfile); } -static void _line(Request& r, StringPtr method_name, MethodParams& params) { - Pool& pool=r.pool(); - - gdImagePtr image=GET_SELF(r, VImage).image; +static void _line(Request& r, MethodParams& params) { + gdImage* image=GET_SELF(r, VImage).image; if(!image) throw Exception(0, - method_name, + 0, "does not contain an image"); image->Line( @@ -870,13 +854,11 @@ static void _line(Request& r, StringPtr image->Color(params.as_int(4, "color must be int", r))); } -static void _fill(Request& r, StringPtr method_name, MethodParams& params) { - Pool& pool=r.pool(); - - gdImagePtr image=GET_SELF(r, VImage).image; +static void _fill(Request& r, MethodParams& params) { + gdImage* image=GET_SELF(r, VImage).image; if(!image) throw Exception(0, - method_name, + 0, "does not contain an image"); image->Fill( @@ -885,13 +867,11 @@ static void _fill(Request& r, StringPtr image->Color(params.as_int(2, "color must be int", r))); } -static void _rectangle(Request& r, StringPtr method_name, MethodParams& params) { - Pool& pool=r.pool(); - - gdImagePtr image=GET_SELF(r, VImage).image; +static void _rectangle(Request& r, MethodParams& params) { + gdImage* image=GET_SELF(r, VImage).image; if(!image) throw Exception(0, - method_name, + 0, "does not contain an image"); image->Rectangle( @@ -902,13 +882,11 @@ static void _rectangle(Request& r, Strin image->Color(params.as_int(4, "color must be int", r))); } -static void _bar(Request& r, StringPtr method_name, MethodParams& params) { - Pool& pool=r.pool(); - - gdImagePtr image=GET_SELF(r, VImage).image; +static void _bar(Request& r, MethodParams& params) { + gdImage* image=GET_SELF(r, VImage).image; if(!image) throw Exception(0, - method_name, + 0, "does not contain an image"); image->FilledRectangle( @@ -927,22 +905,20 @@ static void add_point(Table::element_typ (*p)++; } #endif -static void _replace(Request& r, StringPtr method_name, MethodParams& params) { - Pool& pool=r.pool(); - - gdImagePtr image=GET_SELF(r, VImage).image; +static void _replace(Request& r, MethodParams& params) { + gdImage* image=GET_SELF(r, VImage).image; if(!image) throw Exception(0, - method_name, + 0, "does not contain an image"); - Table* table=params.as_no_junction(2, "coordinates must not be code")->get_table(); + Table* table=params.as_no_junction(2, "coordinates must not be code").get_table(); if(!table) throw Exception(0, - method_name, + 0, "coordinates must be table"); - gdImage::Point *all_p=new(pool) gdImage::Point[table->count()]; + 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(), @@ -950,22 +926,20 @@ static void _replace(Request& r, StringP image->Color(params.as_int(1, "dest color must be int", r))); } -static void _polyline(Request& r, StringPtr method_name, MethodParams& params) { - Pool& pool=r.pool(); - - gdImagePtr image=GET_SELF(r, VImage).image; +static void _polyline(Request& r, MethodParams& params) { + gdImage* image=GET_SELF(r, VImage).image; if(!image) throw Exception(0, - method_name, + 0, "does not contain an image"); - Table* table=params.as_no_junction(1, "coordinates must not be code")->get_table(); + Table* table=params.as_no_junction(1, "coordinates must not be code").get_table(); if(!table) throw Exception(0, - method_name, + 0, "coordinates must be table"); - gdImage::Point* all_p=new(pool) gdImage::Point[table->count()]; + 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(), @@ -973,44 +947,40 @@ static void _polyline(Request& r, String false/*not closed*/); } -static void _polygon(Request& r, StringPtr method_name, MethodParams& params) { - Pool& pool=r.pool(); - - gdImagePtr image=GET_SELF(r, VImage).image; +static void _polygon(Request& r, MethodParams& params) { + gdImage* image=GET_SELF(r, VImage).image; if(!image) throw Exception(0, - method_name, + 0, "does not contain an image"); - Table* table=params.as_no_junction(1, "coordinates must not be code")->get_table(); + Table* table=params.as_no_junction(1, "coordinates must not be code").get_table(); if(!table) throw Exception(0, - method_name, + 0, "coordinates must be table"); - gdImage::Point* all_p=new(pool) gdImage::Point[table->count()]; + 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))); } -static void _polybar(Request& r, StringPtr method_name, MethodParams& params) { - Pool& pool=r.pool(); - - gdImagePtr image=GET_SELF(r, VImage).image; +static void _polybar(Request& r, MethodParams& params) { + gdImage* image=GET_SELF(r, VImage).image; if(!image) throw Exception(0, - method_name, + 0, "does not contain an image"); - Table* table=params.as_no_junction(1, "coordinates must not be code")->get_table(); + Table* table=params.as_no_junction(1, "coordinates must not be code").get_table(); if(!table) throw Exception("parser.runtime", - method_name, + 0, "coordinates must be table"); - gdImage::Point* all_p=new(pool) gdImage::Point[table->count()]; + 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(), @@ -1021,81 +991,72 @@ static void _polybar(Request& r, StringP #define Y(y)(y+index*height) -/// simple gdImage-based font storage & text output -class Font: public PA_Object { -public: - - const static int letter_spacing; - int height; ///< Font heigth - int monospace; ///< Default char width - int spacebarspace; ///< spacebar width - gdImagePtr ifont; - StringPtr alphabet; - - Font(//Pool& pool, - StringPtr aalphabet, - gdImagePtr aifont, int aheight, int amonospace, int aspacebarspace): - alphabet(aalphabet), - height(aheight), monospace(amonospace), spacebarspace(aspacebarspace), - ifont(aifont) { - } - - /* ******************************** char ********************************** */ - - int index_of(char ch) { - if(ch==' ') return -1; - return alphabet->pos(&ch, 1); - } - - int index_width(int index) { - if(index<0) - return spacebarspace; - int tr=ifont->GetTransparent(); - for(int x=ifont->SX()-1; x>=0; x--) { - for(int y=0; yGetPixel(x, Y(y))!=tr) - return x+1; - } - return 0; - } - - void index_display(gdImagePtr image, int x, int y, int index){ - if(index>=0) - ifont->Copy(*image, x, y, 0, Y(0), index_width(index), height); - } - - /* ******************************** string ********************************** */ - - int step_width(int index) { - return letter_spacing + (monospace ? monospace : index_width(index)); - } +// Font class + +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) { +} + +/* ******************************** char ********************************** */ + +size_t Font::index_of(char ch) { + if(ch==' ') return STRING_NOT_FOUND; + return alphabet.pos(ch); +} - // counts trailing letter_spacing, consider this OK. useful for contiuations - int string_width(StringPtr s){ - const char* cstr=s->cstr(); - int result=0; - for(; *cstr; cstr++) - result+=step_width(index_of(*cstr)); - return result; +int Font::index_width(size_t index) { + if(index==STRING_NOT_FOUND) + return spacebarspace; + int tr=ifont->GetTransparent(); + for(int x=ifont->SX()-1; x>=0; x--) { + for(int y=0; yGetPixel(x, Y(y))!=tr) + return x+1; } - - void string_display(gdImagePtr image, int x, int y, StringPtr s){ - const char* cstr=s->cstr(); - if(cstr) for(; *cstr; cstr++) { - int index=index_of(*cstr); - index_display(image, x, y, index); - x+=step_width(index); - } + return 0; +} + +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); +} + +/* ******************************** string ********************************** */ + +int Font::step_width(int index) { + return letter_spacing + (monospace ? monospace : index_width(index)); +} + +// counts trailing letter_spacing, consider this OK. useful for contiuations +int Font::string_width(const String& s){ + const char* cstr=s.cstr(); + int result=0; + for(const char* current=cstr; *current; current++) + result+=step_width(index_of(*current)); + return result; +} + +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); + index_display(image, x, y, index); + x+=step_width(index); } - -}; -const int Font::letter_spacing=1; +} + +// -static void _font(Request& r, StringPtr method_name, MethodParams& params) { - Pool& pool=r.pool(); - StringPtr alphabet=params.as_string(0, "alphabet must not be code"); - gdImagePtr image=load(r, method_name, params.as_string(1, "file_name must not be code")); +static void _font(Request& r, MethodParams& params) { + const String& alphabet=params.as_string(0, "alphabet must not be code"); + gdImage* image=load(r, params.as_string(1, "file_name must not be code")); int spacebar_width=params.as_int(2, "spacebar_width must be int", r); int monospace_width; if(params.count()>3) { @@ -1105,29 +1066,27 @@ static void _font(Request& r, StringPtr } else monospace_width=0; - if(!alphabet->size()) + if(!alphabet.length()) throw Exception("parser.runtime", - method_name, + 0, "alphabet must not be empty"); - if(int remainder=image->SY() % alphabet->size()) + if(int remainder=image->SY() % alphabet.length()) throw Exception("parser.runtime", - method_name, + 0, "font-file height(%d) not divisable by alphabet size(%d), remainder=%d", - image->SY(), alphabet->size(), remainder); + image->SY(), alphabet.length(), remainder); - GET_SELF(r, VImage).font=FontPtr(new Font(//pool, + GET_SELF(r, VImage).font=new Font( alphabet, image, - image->SY() / alphabet->size(), monospace_width, spacebar_width)); + image->SY() / alphabet.length(), monospace_width, spacebar_width); } -static void _text(Request& r, StringPtr method_name, MethodParams& params) { - Pool& pool=r.pool(); - +static void _text(Request& r, MethodParams& params) { int x=params.as_int(0, "x must be int", r); int y=params.as_int(1, "y must be int", r); - StringPtr s=params.as_string(2, "text must not be code"); + const String& s=params.as_string(2, "text must not be code"); VImage& vimage=GET_SELF(r, VImage); if(vimage.image) @@ -1135,40 +1094,36 @@ static void _text(Request& r, StringPtr vimage.font->string_display(vimage.image, x, y, s); else throw Exception("parser.runtime", - method_name, + 0, "set the font first"); else throw Exception(0, - method_name, + 0, "does not contain an image"); } -static void _length(Request& r, StringPtr method_name, MethodParams& params) { - Pool& pool=r.pool(); - - const StringPtr s=params.as_string(0, "text must not be code"); +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(ValuePtr(new VInt(vimage.font->string_width(s)))); + r.write_no_lang(*new VInt(vimage.font->string_width(s))); } else throw Exception("parser.runtime", - method_name, + 0, "set the font first"); else throw Exception(0, - method_name, + 0, "does not contain an image"); } -static void _arc(Request& r, StringPtr method_name, MethodParams& params) { - Pool& pool=r.pool(); - - gdImagePtr image=GET_SELF(r, VImage).image; +static void _arc(Request& r, MethodParams& params) { + gdImage* image=GET_SELF(r, VImage).image; if(!image) throw Exception(0, - method_name, + 0, "does not contain an image"); image->Arc( @@ -1181,13 +1136,11 @@ static void _arc(Request& r, StringPtr m image->Color(params.as_int(6, "cx must be int", r))); } -static void _sector(Request& r, StringPtr method_name, MethodParams& params) { - Pool& pool=r.pool(); - - gdImagePtr image=GET_SELF(r, VImage).image; +static void _sector(Request& r, MethodParams& params) { + gdImage* image=GET_SELF(r, VImage).image; if(!image) throw Exception(0, - method_name, + 0, "does not contain an image"); image->Sector( @@ -1200,13 +1153,11 @@ static void _sector(Request& r, StringPt image->Color(params.as_int(6, "color must be int", r))); } -static void _circle(Request& r, StringPtr method_name, MethodParams& params) { - Pool& pool=r.pool(); - - gdImagePtr image=GET_SELF(r, VImage).image; +static void _circle(Request& r, MethodParams& params) { + gdImage* image=GET_SELF(r, VImage).image; if(!image) throw Exception(0, - method_name, + 0, "does not contain an image"); int size=params.as_int(2, "radius must be int", r)*2; @@ -1220,36 +1171,33 @@ static void _circle(Request& r, StringPt image->Color(params.as_int(3, "color must be int", r))); } -gdImagePtr as_image(Pool& pool, StringPtr method_name, MethodParams& params, - int index, const char* msg) { - gdImagePtr src(0); +gdImage* as_image(MethodParams& params, int index, const char* msg) { + gdImage* src=0; - ValuePtr value=params.as_no_junction(index, msg); + Value& value=params.as_no_junction(index, msg); - if(Value* vimage=value->as(VIMAGE_TYPE, false)) { + if(Value* vimage=value.as(VIMAGE_TYPE, false)) { src=static_cast(vimage)->image; if(!src) throw Exception("parser.runtime", - method_name, + 0, msg); } else throw Exception("parser.runtime", - method_name, + 0, msg); return src; } -static void _copy(Request& r, StringPtr method_name, MethodParams& params) { - Pool& pool=r.pool(); - - gdImagePtr dest=GET_SELF(r, VImage).image; +static void _copy(Request& r, MethodParams& params) { + gdImage* dest=GET_SELF(r, VImage).image; if(!dest) throw Exception(0, - method_name, + 0, "self does not contain an image"); - gdImagePtr src=as_image(pool, method_name, 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); @@ -1288,7 +1236,7 @@ MImage::MImage(): Methoded("image") { add_native_method("create", Method::CT_DYNAMIC, _create, 2, 3); // ^image.gif[] - add_native_method("gif", Method::CT_DYNAMIC, _gif, 0, 0); + add_native_method("gif", Method::CT_DYNAMIC, _gif, 0, 1); // ^image.line(x0;y0;x1;y1;color) add_native_method("line", Method::CT_DYNAMIC, _line, 5, 5);