|
|
| version 1.66, 2002/02/08 08:31:31 | version 1.74, 2002/08/01 11:41:12 |
|---|---|
| Line 1 | Line 1 |
| /** @file | /** @file |
| Parser: @b image parser class. | Parser: @b image parser class. |
| Copyright(c) 2001, 2002 ArtLebedev Group(http://www.artlebedev.com) | Copyright(c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com) |
| Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru) | Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru) |
| $Id$ | |
| */ | */ |
| static const char* IDENT_IMAGE_C="$Date$"; | |
| /* | /* |
| jpegsize: gets the width and height (in pixels) of a jpeg file | jpegsize: gets the width and height (in pixels) of a jpeg file |
| Andrew Tong, werdna@ugcs.caltech.edu February 14, 1995 | Andrew Tong, werdna@ugcs.caltech.edu February 14, 1995 |
| Line 25 | Line 25 |
| #include "pa_vfile.h" | #include "pa_vfile.h" |
| #include "pa_vimage.h" | #include "pa_vimage.h" |
| // defines | |
| #define IMAGE_CLASS_NAME "image" | |
| // class | // class |
| class MImage : public Methoded { | class MImage : public Methoded { |
| Line 83 private: | Line 79 private: |
| }; | }; |
| #endif | #endif |
| /// PNG file header | |
| struct PNG_Header { | |
| char dummy[12]; | |
| char signature[4]; //< must be "IHDR" | |
| unsigned char high_width[2]; //< image width high bytes [we ignore for now] | |
| unsigned char width[2]; //< image width low bytes | |
| unsigned char high_height[2]; //< image height high bytes [we ignore for now] | |
| unsigned char height[4]; //< image height | |
| }; | |
| /// GIF file header | /// GIF file header |
| struct GIF_Header { | struct GIF_Header { |
| char type[3]; // 'GIF' | char signature[3]; // 'GIF' |
| char version[3]; | char version[3]; |
| unsigned char width[2]; | unsigned char width[2]; |
| unsigned char height[2]; | unsigned char height[2]; |
| Line 128 void measure_gif(Pool& pool, const Strin | Line 134 void measure_gif(Pool& pool, const Strin |
| void *buf; | void *buf; |
| const int head_size=sizeof(GIF_Header); | const int head_size=sizeof(GIF_Header); |
| if(reader.read(buf, head_size)<head_size) | if(reader.read(buf, head_size)<head_size) |
| throw Exception(0, 0, | throw Exception("image.format", |
| origin_string, | origin_string, |
| "not GIF file - too small"); | "not GIF file - too small"); |
| GIF_Header *head=(GIF_Header *)buf; | GIF_Header *head=(GIF_Header *)buf; |
| if(strncmp(head->type, "GIF", 3)!=0) | if(strncmp(head->signature, "GIF", 3)!=0) |
| throw Exception(0, 0, | throw Exception("image.format", |
| origin_string, | origin_string, |
| "not GIF file - wrong signature"); | "not GIF file - wrong signature"); |
| Line 153 void measure_jpeg(Pool& pool, const Stri | Line 159 void measure_jpeg(Pool& pool, const Stri |
| void *buf; | void *buf; |
| const size_t prefix_size=2; | const size_t prefix_size=2; |
| if(reader.read(buf, prefix_size)<prefix_size) | if(reader.read(buf, prefix_size)<prefix_size) |
| throw Exception(0, 0, | throw Exception("image.format", |
| origin_string, | origin_string, |
| "not JPEG file - too small"); | "not JPEG file - too small"); |
| unsigned char *signature=(unsigned char *)buf; | unsigned char *signature=(unsigned char *)buf; |
| if(!(signature[0]==0xFF && signature[1]==0xD8)) | if(!(signature[0]==0xFF && signature[1]==0xD8)) |
| throw Exception(0, 0, | throw Exception("image.format", |
| origin_string, | origin_string, |
| "not JPEG file - wrong signature"); | "not JPEG file - wrong signature"); |
| Line 194 void measure_jpeg(Pool& pool, const Stri | Line 200 void measure_jpeg(Pool& pool, const Stri |
| } | } |
| if(!found) | if(!found) |
| throw Exception(0, 0, | throw Exception("image.format", |
| origin_string, | origin_string, |
| "broken JPEG file - size frame not found"); | "broken JPEG file - size frame not found"); |
| } | } |
| void measure_png(Pool& pool, const String *origin_string, | |
| Measure_reader& reader, int& width, int& height) { | |
| void *buf; | |
| const int head_size=sizeof(PNG_Header); | |
| if(reader.read(buf, head_size)<head_size) | |
| throw Exception("image.format", | |
| origin_string, | |
| "not PNG file - too small"); | |
| PNG_Header *head=(PNG_Header *)buf; | |
| if(strncmp(head->signature, "IHDR", 4)!=0) | |
| throw Exception("image.format", | |
| origin_string, | |
| "not PNG file - wrong signature"); | |
| width=big_endian_to_int(head->width); | |
| height=big_endian_to_int(head->height); | |
| } | |
| // measure center | // measure center |
| void measure(Pool& pool, const String& file_name, | void measure(Pool& pool, const String& file_name, |
| Line 209 void measure(Pool& pool, const String& f | Line 235 void measure(Pool& pool, const String& f |
| measure_gif(pool, &file_name, reader, width, height); | measure_gif(pool, &file_name, reader, width, height); |
| else if(strcasecmp(cext, "JPG")==0 || strcasecmp(cext, "JPEG")==0) | else if(strcasecmp(cext, "JPG")==0 || strcasecmp(cext, "JPEG")==0) |
| measure_jpeg(pool, &file_name, reader, width, height); | measure_jpeg(pool, &file_name, reader, width, height); |
| else if(strcasecmp(cext, "PNG")==0) | |
| measure_png(pool, &file_name, reader, width, height); | |
| else | else |
| throw Exception(0, 0, | throw Exception("image.format", |
| &file_name, | &file_name, |
| "unhandled image file name extension '%s'", cext); | "unhandled image file name extension '%s'", cext); |
| } else | } else |
| throw Exception(0, 0, | throw Exception("image.format", |
| &file_name, | &file_name, |
| "can not determine image type - no file name extension"); | "can not determine image type - no file name extension"); |
| } | } |
| Line 314 static void _html(Request& r, const Stri | Line 342 static void _html(Request& r, const Stri |
| Hash *attribs=0; | Hash *attribs=0; |
| if(params->size()) { | if(params->size()) { |
| Value &vattribs=r.process(params->get(0), | // for backward compatibility: someday was ^html{} |
| 0/*no name*/, | Value &vattribs=r.process_to_value(params->get(0), |
| /*0/*no name* /,*/ | |
| false/*don't intercept string*/); | false/*don't intercept string*/); |
| if(vattribs.is_defined()) // allow 'void' | if(vattribs.is_defined()) // allow 'void' |
| if(attribs=vattribs.get_hash(&method_name)) { | if(attribs=vattribs.get_hash(&method_name)) { |
| Attrib_info attrib_info={&tag, 0}; | Attrib_info attrib_info={&tag, 0}; |
| attribs->for_each(append_attrib_pair, &attrib_info); | attribs->for_each(append_attrib_pair, &attrib_info); |
| } else | } else |
| throw Exception(0, 0, | throw Exception("parser.runtime", |
| &method_name, | &method_name, |
| "attributes must be hash"); | "attributes must be hash"); |
| } | } |
| Line 333 static void _html(Request& r, const Stri | Line 362 static void _html(Request& r, const Stri |
| r.write_pass_lang(tag); | r.write_pass_lang(tag); |
| } | } |
| /// @test wrap FILE to auto-object | |
| static gdImage *load(Request& r, const String& method_name, | static gdImage *load(Request& r, const String& method_name, |
| const String& file_name){ | const String& file_name){ |
| Pool& pool=r.pool(); | Pool& pool=r.pool(); |
| Line 343 static gdImage *load(Request& r, const S | Line 373 static gdImage *load(Request& r, const S |
| bool ok=image.CreateFromGif(f); | bool ok=image.CreateFromGif(f); |
| fclose(f); | fclose(f); |
| if(!ok) | if(!ok) |
| throw Exception(0, 0, | throw Exception("image.format", |
| &file_name, | &file_name, |
| "is not in GIF format"); | "is not in GIF format"); |
| return ℑ | return ℑ |
| } else { | } else { |
| throw Exception(0, 0, | throw Exception("file.missing", |
| &method_name, | &method_name, |
| "can not open '%s'", file_name_cstr); | "can not open '%s'", file_name_cstr); |
| return 0; | return 0; |
| Line 386 static void _gif(Request& r, const Strin | Line 416 static void _gif(Request& r, const Strin |
| gdImage *image=static_cast<VImage *>(r.self)->image; | gdImage *image=static_cast<VImage *>(r.self)->image; |
| if(!image) | if(!image) |
| throw Exception(0, 0, | throw Exception(0, |
| &method_name, | &method_name, |
| "does not contain an image"); | "does not contain an image"); |
| Line 407 static void _line(Request& r, const Stri | Line 437 static void _line(Request& r, const Stri |
| gdImage *image=static_cast<VImage *>(r.self)->image; | gdImage *image=static_cast<VImage *>(r.self)->image; |
| if(!image) | if(!image) |
| throw Exception(0, 0, | throw Exception(0, |
| &method_name, | &method_name, |
| "does not contain an image"); | "does not contain an image"); |
| Line 424 static void _fill(Request& r, const Stri | Line 454 static void _fill(Request& r, const Stri |
| gdImage *image=static_cast<VImage *>(r.self)->image; | gdImage *image=static_cast<VImage *>(r.self)->image; |
| if(!image) | if(!image) |
| throw Exception(0, 0, | throw Exception(0, |
| &method_name, | &method_name, |
| "does not contain an image"); | "does not contain an image"); |
| Line 439 static void _rectangle(Request& r, const | Line 469 static void _rectangle(Request& r, const |
| gdImage *image=static_cast<VImage *>(r.self)->image; | gdImage *image=static_cast<VImage *>(r.self)->image; |
| if(!image) | if(!image) |
| throw Exception(0, 0, | throw Exception(0, |
| &method_name, | &method_name, |
| "does not contain an image"); | "does not contain an image"); |
| Line 456 static void _bar(Request& r, const Strin | Line 486 static void _bar(Request& r, const Strin |
| gdImage *image=static_cast<VImage *>(r.self)->image; | gdImage *image=static_cast<VImage *>(r.self)->image; |
| if(!image) | if(!image) |
| throw Exception(0, 0, | throw Exception(0, |
| &method_name, | &method_name, |
| "does not contain an image"); | "does not contain an image"); |
| Line 483 static void _replace(Request& r, const S | Line 513 static void _replace(Request& r, const S |
| gdImage *image=static_cast<VImage *>(r.self)->image; | gdImage *image=static_cast<VImage *>(r.self)->image; |
| if(!image) | if(!image) |
| throw Exception(0, 0, | throw Exception(0, |
| &method_name, | &method_name, |
| "does not contain an image"); | "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) | if(!table) |
| throw Exception(0, 0, | throw Exception(0, |
| &method_name, | &method_name, |
| "coordinates must be table"); | "coordinates must be table"); |
| Line 506 static void _polyline(Request& r, const | Line 536 static void _polyline(Request& r, const |
| gdImage *image=static_cast<VImage *>(r.self)->image; | gdImage *image=static_cast<VImage *>(r.self)->image; |
| if(!image) | if(!image) |
| throw Exception(0, 0, | throw Exception(0, |
| &method_name, | &method_name, |
| "does not contain an image"); | "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) | if(!table) |
| throw Exception(0, 0, | throw Exception(0, |
| &method_name, | &method_name, |
| "coordinates must be table"); | "coordinates must be table"); |
| Line 529 static void _polygon(Request& r, const S | Line 559 static void _polygon(Request& r, const S |
| gdImage *image=static_cast<VImage *>(r.self)->image; | gdImage *image=static_cast<VImage *>(r.self)->image; |
| if(!image) | if(!image) |
| throw Exception(0, 0, | throw Exception(0, |
| &method_name, | &method_name, |
| "does not contain an image"); | "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) | if(!table) |
| throw Exception(0, 0, | throw Exception(0, |
| &method_name, | &method_name, |
| "coordinates must be table"); | "coordinates must be table"); |
| Line 551 static void _polybar(Request& r, const S | Line 581 static void _polybar(Request& r, const S |
| gdImage *image=static_cast<VImage *>(r.self)->image; | gdImage *image=static_cast<VImage *>(r.self)->image; |
| if(!image) | if(!image) |
| throw Exception(0, 0, | throw Exception(0, |
| &method_name, | &method_name, |
| "does not contain an image"); | "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) | if(!table) |
| throw Exception(0, 0, | throw Exception("parser.runtime", |
| &method_name, | &method_name, |
| "coordinates must be table"); | "coordinates must be table"); |
| Line 652 static void _font(Request& r, const Stri | Line 682 static void _font(Request& r, const Stri |
| monospace_width=0; | monospace_width=0; |
| if(!alphabet.size()) | if(!alphabet.size()) |
| throw Exception(0, 0, | throw Exception("parser.runtime", |
| &method_name, | &method_name, |
| "alphabet must not be empty"); | "alphabet must not be empty"); |
| Line 674 static void _text(Request& r, const Stri | Line 704 static void _text(Request& r, const Stri |
| if(vimage.font) | if(vimage.font) |
| vimage.font->string_display(*vimage.image, x, y, s); | vimage.font->string_display(*vimage.image, x, y, s); |
| else | else |
| throw Exception(0, 0, | throw Exception("parser.runtime", |
| &method_name, | &method_name, |
| "set the font first"); | "set the font first"); |
| else | else |
| throw Exception(0, 0, | throw Exception(0, |
| &method_name, | &method_name, |
| "does not contain an image"); | "does not contain an image"); |
| } | } |
| Line 691 static void _length(Request& r, const St | Line 721 static void _length(Request& r, const St |
| VImage& vimage=*static_cast<VImage *>(r.self); | VImage& vimage=*static_cast<VImage *>(r.self); |
| if(vimage.image) | if(vimage.image) |
| if(vimage.font) { | if(vimage.font) { |
| VInt& result=*new(pool) VInt(pool, vimage.font->string_width(s)); | r.write_no_lang(*new(pool) VInt(pool, vimage.font->string_width(s))); |
| result.set_name(method_name); | |
| r.write_assign_lang(result); | |
| } else | } else |
| throw Exception(0, 0, | throw Exception("parser.runtime", |
| &method_name, | &method_name, |
| "set the font first"); | "set the font first"); |
| else | else |
| throw Exception(0, 0, | throw Exception(0, |
| &method_name, | &method_name, |
| "does not contain an image"); | "does not contain an image"); |
| } | } |
| Line 709 static void _arc(Request& r, const Strin | Line 737 static void _arc(Request& r, const Strin |
| gdImage *image=static_cast<VImage *>(r.self)->image; | gdImage *image=static_cast<VImage *>(r.self)->image; |
| if(!image) | if(!image) |
| throw Exception(0, 0, | throw Exception(0, |
| &method_name, | &method_name, |
| "does not contain an image"); | "does not contain an image"); |
| Line 728 static void _sector(Request& r, const St | Line 756 static void _sector(Request& r, const St |
| gdImage *image=static_cast<VImage *>(r.self)->image; | gdImage *image=static_cast<VImage *>(r.self)->image; |
| if(!image) | if(!image) |
| throw Exception(0, 0, | throw Exception(0, |
| &method_name, | &method_name, |
| "does not contain an image"); | "does not contain an image"); |
| Line 747 static void _circle(Request& r, const St | Line 775 static void _circle(Request& r, const St |
| gdImage *image=static_cast<VImage *>(r.self)->image; | gdImage *image=static_cast<VImage *>(r.self)->image; |
| if(!image) | if(!image) |
| throw Exception(0, 0, | throw Exception(0, |
| &method_name, | &method_name, |
| "does not contain an image"); | "does not contain an image"); |
| Line 767 gdImage& as_image(Pool& pool, const Stri | Line 795 gdImage& as_image(Pool& pool, const Stri |
| Value& value=params->as_no_junction(index, msg); | Value& value=params->as_no_junction(index, msg); |
| if(strcmp(value.type(), VIMAGE_TYPE)!=0) | if(strcmp(value.type(), VIMAGE_TYPE)!=0) |
| throw Exception(0, 0, | throw Exception("parser.runtime", |
| &method_name, | &method_name, |
| msg); | msg); |
| gdImage *src=static_cast<VImage *>(&value)->image; | gdImage *src=static_cast<VImage *>(&value)->image; |
| if(!src) | if(!src) |
| throw Exception(0, 0, | throw Exception("parser.runtime", |
| &method_name, | &method_name, |
| msg); | msg); |
| Line 785 static void _copy(Request& r, const Stri | Line 813 static void _copy(Request& r, const Stri |
| gdImage *dest=static_cast<VImage *>(r.self)->image; | gdImage *dest=static_cast<VImage *>(r.self)->image; |
| if(!dest) | if(!dest) |
| throw Exception(0, 0, | throw Exception(0, |
| &method_name, | &method_name, |
| "self does not contain an image"); | "self does not contain an image"); |
| Line 812 static void _copy(Request& r, const Stri | Line 840 static void _copy(Request& r, const Stri |
| // constructor | // constructor |
| MImage::MImage(Pool& apool) : Methoded(apool) { | MImage::MImage(Pool& apool) : Methoded(apool, "image") { |
| set_name(*NEW String(pool(), IMAGE_CLASS_NAME)); | |
| // ^image:measure[DATA] | // ^image:measure[DATA] |
| add_native_method("measure", Method::CT_DYNAMIC, _measure, 1, 1); | add_native_method("measure", Method::CT_DYNAMIC, _measure, 1, 1); |