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