Annotation of parser3/src/classes/image.C, revision 1.31
1.1 paf 1: /** @file
2: Parser: @b image parser class.
3:
1.16 paf 4: Copyright(c) 2001 ArtLebedev Group(http://www.artlebedev.com)
1.1 paf 5:
1.16 paf 6: Author: Alexander Petrosyan <paf@design.ru>(http://design.ru/paf)
1.1 paf 7:
1.31 ! parser 8: $Id: image.C,v 1.30 2001/07/07 16:38:01 parser Exp $
! 9: */
! 10: static const char *RCSId="$Id: image.C,v 1.30 2001/07/07 16:38:01 parser Exp $";
! 11:
! 12: /*
! 13: jpegsize: gets the width and height (in pixels) of a jpeg file
! 14: Andrew Tong, werdna@ugcs.caltech.edu February 14, 1995
! 15: modified slightly by alex@ed.ac.uk
! 16: and further still by rjray@uswest.com
! 17: optimization and general re-write from tmetro@vl.com
! 18: from perl by paf@design.ru
1.1 paf 19: */
20:
21: #include "pa_config_includes.h"
22:
1.8 paf 23: #include "gif.h"
1.6 paf 24:
1.1 paf 25: #include "pa_common.h"
26: #include "pa_request.h"
27: #include "pa_vfile.h"
28: #include "pa_vimage.h"
29:
1.22 paf 30: // defines
1.1 paf 31:
1.22 paf 32: #define IMAGE_CLASS_NAME "image"
33:
34: // class
35:
36: class MImage : public Methoded {
37: public: // VStateless_class
38: Value *create_new_value(Pool& pool) { return new(pool) VImage(pool); }
39:
40: public:
41: MImage(Pool& pool);
1.24 paf 42:
43: public: // Methoded
1.22 paf 44: bool used_directly() { return true; }
45:
46: };
1.1 paf 47:
48: // helpers
49:
1.21 paf 50: /// simple buffered reader[from memory/file], used in _measure
1.1 paf 51: class Measure_reader {
52: public:
1.31 ! parser 53: enum { READ_CHUNK_SIZE=0x400*10 };// 10K
1.16 paf 54: typedef size_t(*Func)(void *& buf, size_t limit, void *info);
1.1 paf 55:
56: Measure_reader(Func afunc, void *ainfo) :
57: func(afunc), info(ainfo),
58: chunk(0), offset(0), size(0) {
59: }
60:
1.31 ! parser 61: size_t read(void *&buf, size_t limit) {
1.3 paf 62: if(offset+limit>size) // nothing left
63: if(offset==0 || limit==1) { // only one-byte continuations allowed
64: size=(*func)(chunk, READ_CHUNK_SIZE, info);
65: offset=0;
66: } else
1.16 paf 67: return 0;// as if EOF
1.1 paf 68: if(!size) // EOF
69: return 0;
70:
71: // something left
72: size_t read_size=min(offset+limit, size)-offset;
73: buf=((unsigned char *)chunk)+offset;
74: offset+=read_size;
75: return read_size;
76: }
77:
78: private:
79: Func func;
80: void *info;
81:
82: void *chunk;
83: size_t offset;
84: size_t size;
85: };
86:
1.21 paf 87: /// GIF file header
1.1 paf 88: struct GIF_Header {
1.16 paf 89: char type[3]; // 'GIF'
1.1 paf 90: char version[3];
91: unsigned char width[2];
92: unsigned char height[2];
93: char dif;
94: char fonColor;
95: char nulls;
96: };
97:
1.31 ! parser 98: /// JPEG record head
! 99: struct JPG_Segment_head {
! 100: unsigned char marker;
! 101: unsigned char code;
! 102: unsigned char length[2];
1.1 paf 103: };
1.21 paf 104: /// JPEG frame header
1.31 ! parser 105: struct JPG_Size_segment_body {
1.27 parser 106: char data; //< data precision of bits/sample
1.31 ! parser 107: unsigned char height[2]; //< image height
! 108: unsigned char width[2]; //< image width
1.27 parser 109: char numComponents; //< number of color components
1.1 paf 110: };
111:
112: //
113:
1.31 ! parser 114: inline short bytes_to_int(unsigned char chars[2]) {
! 115: return(short)((chars[1]<<8) + chars[0]);
1.1 paf 116: }
117:
118: void measure_gif(Pool& pool, const String *origin_string,
119: Measure_reader& reader, int& width, int& height) {
120:
1.31 ! parser 121: void *buf;
1.1 paf 122: const int head_size=sizeof(GIF_Header);
123: if(reader.read(buf, head_size)<head_size)
124: PTHROW(0, 0,
125: origin_string,
126: "broken GIF header - file size is less then %d bytes", head_size);
1.31 ! parser 127: GIF_Header *head=(GIF_Header *)buf;
1.1 paf 128:
1.31 ! parser 129: if(strncmp(head->type, "GIF", 3)!=0)
1.1 paf 130: PTHROW(0, 0,
131: origin_string,
132: "bad image file - GIF signature not found");
133:
1.31 ! parser 134: width=bytes_to_int(head->width);
! 135: height=bytes_to_int(head->height);
1.1 paf 136: }
137:
138: void measure_jpeg(Pool& pool, const String *origin_string,
139: Measure_reader& reader, int& width, int& height) {
1.2 paf 140: // JFIF format markers
1.31 ! parser 141: const unsigned char MARKER=0xFF;
! 142: const unsigned char SIZE_FIRST=0xC0;
! 143: const unsigned char SIZE_LAST=0xC3;
1.2 paf 144:
1.31 ! parser 145: void *buf;
1.18 paf 146: const size_t prefix_size=2;
1.31 ! parser 147: if(reader.read(buf, prefix_size)<prefix_size)
1.1 paf 148: PTHROW(0, 0,
149: origin_string,
150: "broken JPEG file - size is less then %d bytes", prefix_size);
1.31 ! parser 151: unsigned char *signature=(unsigned char *)buf;
1.1 paf 152:
1.31 ! parser 153: if(!(signature[0]==0xFF && signature[1]==0xD8))
1.1 paf 154: PTHROW(0, 0,
155: origin_string,
1.31 ! parser 156: "broken JPEG file - signature not found");
! 157:
! 158: bool found=false;
! 159: while(true) {
! 160: void *buf;
! 161: // Extract the segment header.
! 162: if(reader.read(buf, sizeof(JPG_Segment_head))<sizeof(JPG_Segment_head))
! 163: break;
! 164: JPG_Segment_head *head=(JPG_Segment_head *)buf;
! 165:
! 166: // Verify that it's a valid segment.
! 167: if(head->marker!=MARKER)
1.1 paf 168: break;
1.31 ! parser 169:
! 170: if(head->code >= SIZE_FIRST && head->code <= SIZE_LAST) {
! 171: // Segments that contain size info
! 172: if(reader.read(buf, sizeof(JPG_Size_segment_body))<sizeof(JPG_Size_segment_body))
! 173: break;
! 174: JPG_Size_segment_body *body=(JPG_Size_segment_body *)buf;
! 175:
! 176: width=bytes_to_int(body->width);
! 177: height=bytes_to_int(body->height);
! 178: found=true;
1.1 paf 179: break;
1.31 ! parser 180: } else {
! 181: // Dummy read to skip over data
! 182: size_t limit=bytes_to_int(head->length) - 2;
! 183: if(reader.read(buf, limit)<limit)
! 184: break;
! 185: }
! 186: }
! 187:
! 188: if(!found)
1.16 paf 189: PTHROW(0, 0,
190: origin_string,
1.31 ! parser 191: "broken JPEG file - size frame not found");
1.1 paf 192: }
193:
194: // measure center
195:
196: void measure(Pool& pool, const String& file_name,
197: Measure_reader& reader, int& width, int& height) {
198: if(const char *cext=strrchr(file_name.cstr(), '.')) {
199: cext++;
200: if(strcasecmp(cext, "GIF")==0)
201: measure_gif(pool, &file_name, reader, width, height);
202: else if(strcasecmp(cext, "JPG")==0 || strcasecmp(cext, "JPEG")==0)
203: measure_jpeg(pool, &file_name, reader, width, height);
204: else
205: PTHROW(0, 0,
206: &file_name,
207: "unhandled image file name extension '%s'", cext);
208: } else
209: PTHROW(0, 0,
210: &file_name,
211: "can not determine image type - no file name extension");
212: }
213:
1.21 paf 214: /// used by image: _measure / read_mem
1.1 paf 215: struct Read_mem_info {
216: unsigned char *ptr;
217: unsigned char *eof;
218: };
219: static size_t read_mem(void*& buf, size_t limit, void *info) {
220: Read_mem_info& rmi=*static_cast<Read_mem_info *>(info);
221: buf=rmi.ptr;
222: size_t read_size=min(limit, (size_t)(rmi.eof-rmi.ptr));
223: rmi.ptr+=read_size;
224: return read_size;
225: }
226:
1.21 paf 227: /// used by image: _measure / read_disk
1.1 paf 228: struct Read_disk_info {
229: const String *file_spec;
230: size_t offset;
231: };
232: static size_t read_disk(void*& buf, size_t limit, void *info) {
233: Read_disk_info& rdi=*static_cast<Read_disk_info *>(info);
234: Pool& pool=rdi.file_spec->pool();
235:
236: size_t read_size;
237: file_read(pool, *rdi.file_spec,
238: buf, read_size,
239: false/*as_text*/,
240: true/*fail_on_read_problem*/,
241: rdi.offset, limit);
242:
243: rdi.offset+=read_size;
244: return read_size;
245: }
246:
247: // methods
248:
1.17 paf 249: static void _measure(Request& r, const String& method_name, MethodParams *params) {
1.1 paf 250: Pool& pool=r.pool();
251:
1.30 parser 252: Value& data=params->as_no_junction(0, "data must not be code");
1.1 paf 253:
1.16 paf 254: void *info;Measure_reader::Func read_func;
1.1 paf 255: Read_mem_info read_mem_info;
256: Read_disk_info read_disk_info;
257: const String *file_name;
258: if(data.is_string()) {
259: file_name=data.get_string();
260: read_disk_info.file_spec=&r.absolute(*file_name);
261: read_disk_info.offset=0;
1.16 paf 262: info=&read_disk_info;read_func=read_disk;
1.1 paf 263: } else {
264: const VFile& vfile=*data.as_vfile();
265: file_name=&static_cast<Value *>(vfile.fields().get(*name_name))->as_string();
266: read_mem_info.ptr=(unsigned char *)vfile.value_ptr();
267: read_mem_info.eof=read_mem_info.ptr+vfile.value_size();
1.16 paf 268: info=&read_mem_info;read_func=read_mem;
1.1 paf 269: }
270:
271: Measure_reader reader(read_func, info);
272: int width, height;
273: measure(pool, *file_name, reader, width, height);
274:
1.6 paf 275: static_cast<VImage *>(r.self)->set(file_name, width, height);
1.1 paf 276: }
277:
1.21 paf 278: /// used by image: _html / append_attrib_pair
1.4 paf 279: struct Attrib_info {
1.21 paf 280: String *tag; ///< html tag being constructed
281: Hash *skip; ///< tag attributes not to append to tag string [to skip]
1.4 paf 282: };
1.3 paf 283: static void append_attrib_pair(const Hash::Key& key, Hash::Val *val, void *info) {
1.4 paf 284: Attrib_info& ai=*static_cast<Attrib_info *>(info);
285:
286: if(ai.skip && ai.skip->get(key))
287: return;
288:
1.3 paf 289: Value& value=*static_cast<Value *>(val);
290: // src="a.gif" width=123 ismap[=-1]
1.4 paf 291: *ai.tag << " " << key;
1.26 parser 292: if(value.is_string() || value.as_int()>=0)
1.6 paf 293: *ai.tag << "=\"" << value.as_string() << "\"";
1.3 paf 294: }
1.17 paf 295: static void _html(Request& r, const String& method_name, MethodParams *params) {
1.3 paf 296: Pool& pool=r.pool();
297:
298: String tag(pool);
299: tag << "<img";
1.4 paf 300:
1.18 paf 301: const Hash& fields=static_cast<VImage *>(r.self)->fields();
1.5 paf 302: Hash *attribs=0;
1.4 paf 303:
1.11 paf 304: if(params->size())
1.17 paf 305: if(attribs=params->get(0).get_hash()) {
1.4 paf 306: Attrib_info attrib_info={&tag, 0};
1.5 paf 307: attribs->for_each(append_attrib_pair, &attrib_info);
1.4 paf 308: } else
1.16 paf 309: PTHROW(0, 0,
310: &method_name,
1.5 paf 311: "attributes must be must be hash");
1.4 paf 312:
1.5 paf 313: Attrib_info attrib_info={&tag, attribs};
1.4 paf 314: fields.for_each(append_attrib_pair, &attrib_info);
1.6 paf 315: tag << " />";
1.3 paf 316: r.write_pass_lang(tag);
317: }
1.8 paf 318:
1.16 paf 319: static gdImage *load(Request& r, const String& method_name,
320: const String& file_name){
321: Pool& pool=r.pool();
322:
323: const char *file_name_cstr=r.absolute(file_name).cstr(String::UL_FILE_NAME);
324: if(FILE *f=fopen(file_name_cstr, "rb")) {
325: gdImage& image=*new(pool) gdImage(pool);
1.23 paf 326: bool ok=image.CreateFromGif(f);
1.16 paf 327: fclose(f);
1.23 paf 328: if(!ok)
329: PTHROW(0, 0,
330: &file_name,
331: "is not in GIF format");
1.16 paf 332: return ℑ
333: } else {
334: PTHROW(0, 0,
335: &method_name,
336: "can not open '%s'", file_name_cstr);
337: return 0;
338: }
339: }
340:
341:
1.17 paf 342: static void _load(Request& r, const String& method_name, MethodParams *params) {
1.6 paf 343: Pool& pool=r.pool();
344:
1.30 parser 345: Value& vfile_name=params->as_no_junction(0, "file name must not be code");
1.6 paf 346: const String& file_name=vfile_name.as_string();
347:
1.16 paf 348: gdImage& image=*load(r, method_name, file_name);
349: int width=image.SX();
350: int height=image.SY();
351: static_cast<VImage *>(r.self)->set(&file_name, width, height, &image);
1.6 paf 352: }
353:
1.17 paf 354: static void _create(Request& r, const String& method_name, MethodParams *params) {
1.6 paf 355: Pool& pool=r.pool();
356:
1.26 parser 357: int width=r.process(params->get(0)).as_int();
358: int height=r.process(params->get(1)).as_int();
1.8 paf 359: int bgcolor_value=0xffFFff;
1.6 paf 360: if(params->size()>2)
1.26 parser 361: bgcolor_value=r.process(params->get(2)).as_int();
1.15 paf 362: gdImage& image=*new(pool) gdImage(pool);
363: image.Create(width, height);
364: image.FilledRectangle(0, 0, width-1, height-1, image.Color(bgcolor_value));
365: static_cast<VImage *>(r.self)->set(0, width, height, &image);
1.6 paf 366: }
367:
1.17 paf 368: static void _gif(Request& r, const String& method_name, MethodParams *params) {
1.6 paf 369: Pool& pool=r.pool();
370:
1.9 paf 371: gdImage *image=static_cast<VImage *>(r.self)->image;
1.8 paf 372: if(!image)
1.16 paf 373: PTHROW(0, 0,
374: &method_name,
1.12 paf 375: "does not contain an image");
1.6 paf 376:
377: // could _ but don't thing it's wise to use $image.src for vfile.name
1.10 paf 378:
1.16 paf 379: String out(pool); image->Gif(out);
1.6 paf 380:
381: VFile& vfile=*new(pool) VFile(pool);
382: String& image_gif=*new(pool) String(pool, "image/gif");
1.20 paf 383: vfile.set(false/*not tainted*/,
384: out.cstr(String::UL_AS_IS), out.size(), 0, &image_gif);
1.6 paf 385:
386: r.write_no_lang(vfile);
387: }
388:
1.17 paf 389: static void _line(Request& r, const String& method_name, MethodParams *params) {
1.12 paf 390: Pool& pool=r.pool();
391:
392: gdImage *image=static_cast<VImage *>(r.self)->image;
393: if(!image)
1.16 paf 394: PTHROW(0, 0,
395: &method_name,
1.12 paf 396: "does not contain an image");
397:
398: image->Line(
1.26 parser 399: r.process(params->get(0)).as_int(),
400: r.process(params->get(1)).as_int(),
401: r.process(params->get(2)).as_int(),
402: r.process(params->get(3)).as_int(),
403: image->Color(r.process(params->get(4)).as_int()));
1.13 paf 404: }
405:
1.17 paf 406: static void _fill(Request& r, const String& method_name, MethodParams *params) {
1.13 paf 407: Pool& pool=r.pool();
408:
409: gdImage *image=static_cast<VImage *>(r.self)->image;
410: if(!image)
1.16 paf 411: PTHROW(0, 0,
412: &method_name,
1.13 paf 413: "does not contain an image");
1.12 paf 414:
1.13 paf 415: image->Fill(
1.26 parser 416: r.process(params->get(0)).as_int(),
417: r.process(params->get(1)).as_int(),
418: image->Color(r.process(params->get(2)).as_int()));
1.13 paf 419: }
420:
1.17 paf 421: static void _rectangle(Request& r, const String& method_name, MethodParams *params) {
1.13 paf 422: Pool& pool=r.pool();
423:
424: gdImage *image=static_cast<VImage *>(r.self)->image;
425: if(!image)
1.16 paf 426: PTHROW(0, 0,
427: &method_name,
1.13 paf 428: "does not contain an image");
429:
430: image->Rectangle(
1.26 parser 431: r.process(params->get(0)).as_int(),
432: r.process(params->get(1)).as_int(),
433: r.process(params->get(2)).as_int(),
434: r.process(params->get(3)).as_int(),
435: image->Color(r.process(params->get(4)).as_int()));
1.13 paf 436: }
437:
1.17 paf 438: static void _bar(Request& r, const String& method_name, MethodParams *params) {
1.13 paf 439: Pool& pool=r.pool();
440:
441: gdImage *image=static_cast<VImage *>(r.self)->image;
442: if(!image)
1.16 paf 443: PTHROW(0, 0,
444: &method_name,
1.13 paf 445: "does not contain an image");
446:
447: image->FilledRectangle(
1.26 parser 448: r.process(params->get(0)).as_int(),
449: r.process(params->get(1)).as_int(),
450: r.process(params->get(2)).as_int(),
451: r.process(params->get(3)).as_int(),
452: image->Color(r.process(params->get(4)).as_int()));
1.13 paf 453: }
454:
1.17 paf 455: static void _replace(Request& r, const String& method_name, MethodParams *params) {
1.13 paf 456: Pool& pool=r.pool();
457:
458: gdImage *image=static_cast<VImage *>(r.self)->image;
459: if(!image)
1.16 paf 460: PTHROW(0, 0,
461: &method_name,
1.13 paf 462: "does not contain an image");
463:
464: if((params->size()-2)%2) // I see your thoughts, but that's more readable
1.16 paf 465: PTHROW(0, 0,
466: &method_name,
1.13 paf 467: "y coordinate missing");
468:
469: int n=(params->size()-2)/2;
470:
471: gdImage::Point *p=(gdImage::Point *)pool.malloc(sizeof(gdImage::Point)*n);
472: for(int i=0; i<n; i++) {
1.26 parser 473: p[i].x=r.process(params->get(2+i*2+0)).as_int();
474: p[i].y=r.process(params->get(2+i*2+1)).as_int();
1.13 paf 475: }
1.16 paf 476: image->FilledPolygonReplaceColor(p, n,
1.26 parser 477: image->Color(r.process(params->get(0)).as_int()), // src color
478: image->Color(r.process(params->get(1)).as_int()));// dest color
1.13 paf 479: }
480:
1.17 paf 481: static void _polygon(Request& r, const String& method_name, MethodParams *params) {
1.13 paf 482: Pool& pool=r.pool();
483:
484: gdImage *image=static_cast<VImage *>(r.self)->image;
485: if(!image)
1.16 paf 486: PTHROW(0, 0,
487: &method_name,
1.13 paf 488: "does not contain an image");
489:
490: if((params->size()-1)%2) // [I see..] see now?
1.16 paf 491: PTHROW(0, 0,
492: &method_name,
1.13 paf 493: "y coordinate missing");
494:
495: int n=(params->size()-1)/2;
496:
497: gdImage::Point *p=(gdImage::Point *)pool.malloc(sizeof(gdImage::Point)*n);
498: for(int i=0; i<n; i++) {
1.26 parser 499: p[i].x=r.process(params->get(1+i*2+0)).as_int();
500: p[i].y=r.process(params->get(1+i*2+1)).as_int();
1.13 paf 501: }
1.16 paf 502: image->Polygon(p, n,
1.26 parser 503: image->Color(r.process(params->get(0)).as_int()));
1.13 paf 504: }
505:
1.17 paf 506: static void _polybar(Request& r, const String& method_name, MethodParams *params) {
1.13 paf 507: Pool& pool=r.pool();
508:
509: gdImage *image=static_cast<VImage *>(r.self)->image;
510: if(!image)
1.16 paf 511: PTHROW(0, 0,
512: &method_name,
1.13 paf 513: "does not contain an image");
514:
515: if((params->size()-1)%2) // [I see..] see now?
1.16 paf 516: PTHROW(0, 0,
517: &method_name,
1.13 paf 518: "y coordinate missing");
519:
520: int n=(params->size()-1)/2;
521:
522: gdImage::Point *p=(gdImage::Point *)pool.malloc(sizeof(gdImage::Point)*n);
523: for(int i=0; i<n; i++) {
1.26 parser 524: p[i].x=r.process(params->get(1+i*2+0)).as_int();
525: p[i].y=r.process(params->get(1+i*2+1)).as_int();
1.13 paf 526: }
1.16 paf 527: image->FilledPolygon(p, n,
1.26 parser 528: image->Color(r.process(params->get(0)).as_int()));
1.12 paf 529: }
530:
1.16 paf 531: // font
532:
533: #define Y(y)(y+index*height+1)
1.21 paf 534:
535: /// simple gdImage-based font storage & text output
1.16 paf 536: class Font : public Pooled {
537: public:
538:
1.27 parser 539: int height; //< Font heigth
540: int space; //< Default char width
1.16 paf 541: gdImage& ifont;
542: const String& alphabet;
543:
544: Font(Pool& pool,
545: const String& aalphabet,
546: gdImage& aifont, int aheight, int aspace) : Pooled(pool),
547: alphabet(aalphabet),
548: height(aheight), space(aspace),
549: ifont(aifont) {
550: }
551:
552: /* ******************************** char ********************************** */
553:
554: int index_of(char ch) {
555: if(ch==' ') return -1;
556: return alphabet.pos(&ch, 1);
557: }
558:
559: int index_width(int index) {
560: if(index<0)
561: index=index_of('.');
562: if(index<0)
563: return 0;
564: int tr=ifont.GetTransparent();
565: for(int x=ifont.SX()-1; x>0; x--) {
566: for(int y=0; y<height-1; y++)
567: if(ifont.GetPixel(x, Y(y))!=tr)
568: return x+2;
569: }
570: return 0;
571: }
572:
573: void index_display(gdImage& image, int x, int y, int index){
574: if(index>=0)
575: ifont.Copy(image, x, y, 0, Y(0), index_width(index), height-1);
576: }
577:
578: /* ******************************** string ********************************** */
579: /*
580: int string_width(const char *cstr){
581: int result=0;
582: for(; *cstr; cstr++)
583: result+=index_width(index_of(*cstr));
584: return result;
585: }
586: */
587:
588: void string_display(gdImage& image, int x, int y, const String& s){
589: const char *cstr=s.cstr(String::UL_AS_IS);
590: if(cstr) for(; *cstr; cstr++) {
591: int index=index_of(*cstr);
592: index_display(image, x, y, index);
593: x+=space ? space : index_width(index);
594: }
595: }
596:
597: };
1.17 paf 598: static void _font(Request& r, const String& method_name, MethodParams *params) {
1.16 paf 599: Pool& pool=r.pool();
600:
1.30 parser 601: Value& valphabet=params->as_no_junction(0, "alphabet must not be code");
602: Value& file_name=params->as_no_junction(1, "file_name must not be code");
1.26 parser 603: int height=r.process(params->get(2)).as_int();
1.16 paf 604:
1.26 parser 605: int width=params->size()>3?r.process(params->get(3)).as_int():0;
1.16 paf 606:
607: static_cast<VImage *>(r.self)->font=new(pool) Font(pool,
608: valphabet.as_string(),
609: *load(r, method_name, file_name.as_string()),
610: height, width);
611: }
612:
1.17 paf 613: static void _text(Request& r, const String& method_name, MethodParams *params) {
1.16 paf 614: Pool& pool=r.pool();
615:
1.26 parser 616: int x=r.process(params->get(0)).as_int();
617: int y=r.process(params->get(1)).as_int();
1.17 paf 618: const String& s=r.process(params->get(2)).as_string();
1.16 paf 619:
620: VImage& vimage=*static_cast<VImage *>(r.self);
621: if(vimage.image)
622: if(vimage.font)
623: vimage.font->string_display(*vimage.image, x, y, s);
624: else
625: PTHROW(0, 0,
626: &method_name,
627: "set the font first");
628: else
629: PTHROW(0, 0,
630: &method_name,
631: "does not contain an image");
632: }
633:
1.22 paf 634: // constructor
635:
636: MImage::MImage(Pool& apool) : Methoded(apool) {
637: set_name(*NEW String(pool(), IMAGE_CLASS_NAME));
638:
639:
1.1 paf 640: // ^image:measure[DATA]
1.22 paf 641: add_native_method("measure", Method::CT_DYNAMIC, _measure, 1, 1);
1.3 paf 642:
1.25 paf 643: // ^image.html[]
644: // ^image.html[hash]
1.22 paf 645: add_native_method("html", Method::CT_DYNAMIC, _html, 0, 1);
1.6 paf 646:
1.25 paf 647: // ^image.load[background.gif]
1.22 paf 648: add_native_method("load", Method::CT_DYNAMIC, _load, 1, 1);
1.6 paf 649:
1.25 paf 650: // ^image.create[width;height] bgcolor=white
651: // ^image.create[width;height;bgcolor]
1.22 paf 652: add_native_method("create", Method::CT_DYNAMIC, _create, 2, 3);
1.6 paf 653:
1.25 paf 654: // ^image.gif[]
1.22 paf 655: add_native_method("gif", Method::CT_DYNAMIC, _gif, 0, 0);
1.12 paf 656:
1.25 paf 657: // ^image.line(x0;y0;x1;y1;color)
1.22 paf 658: add_native_method("line", Method::CT_DYNAMIC, _line, 5, 5);
1.13 paf 659:
1.25 paf 660: // ^image.fill(x;y;color)
1.22 paf 661: add_native_method("fill", Method::CT_DYNAMIC, _fill, 3, 3);
1.13 paf 662:
1.25 paf 663: // ^image.rectangle(x0;y0;x1;y1;color)
1.22 paf 664: add_native_method("rectangle", Method::CT_DYNAMIC, _rectangle, 5, 5);
1.13 paf 665:
1.25 paf 666: // ^image.bar(x0;y0;x1;y1;color)
1.22 paf 667: add_native_method("bar", Method::CT_DYNAMIC, _bar, 5, 5);
1.13 paf 668:
1.25 paf 669: // ^image.replace(color-source;color-dest)(x;y)... point coord pairs
1.22 paf 670: add_native_method("replace", Method::CT_DYNAMIC, _replace, 2+3*2, 2+100*2);
1.13 paf 671:
1.25 paf 672: // ^image.polygon(color)(x;y)... point coord pairs
1.22 paf 673: add_native_method("polygon", Method::CT_DYNAMIC, _polygon, 1+3*2, 1+100*2);
1.13 paf 674:
1.25 paf 675: // ^image.polybar(color)(x;y)... point coord pairs
1.22 paf 676: add_native_method("polybar", Method::CT_DYNAMIC, _polybar, 1+3*2, 1+100*2);
1.13 paf 677:
1.25 paf 678: // ^image.font[alPHAbet;font-file-name.gif](height)
679: // ^image.font[alPHAbet;font-file-name.gif](height;width)
1.22 paf 680: add_native_method("font", Method::CT_DYNAMIC, _font, 3, 4);
1.16 paf 681:
1.25 paf 682: // ^image.text(x;y)[text]
1.22 paf 683: add_native_method("text", Method::CT_DYNAMIC, _text, 3, 3);
1.16 paf 684:
1.22 paf 685: }
686:
687: // global variable
688:
689: Methoded *image_class;
690:
691: // creator
692:
693: Methoded *MImage_create(Pool& pool) {
694: return image_class=new(pool) MImage(pool);
1.1 paf 695: }
E-mail: