Annotation of parser3/src/classes/image.C, revision 1.22
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.22 ! paf 8: $Id: image.C,v 1.21.2.4 2001/04/28 07:27:31 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);
337: image.CreateFromGif(f);
338: fclose(f);
339: return ℑ
340: } else {
341: PTHROW(0, 0,
342: &method_name,
343: "can not open '%s'", file_name_cstr);
344: return 0;
345: }
346: }
347:
348:
1.6 paf 349: /// ^image.load[background.gif]
1.17 paf 350: static void _load(Request& r, const String& method_name, MethodParams *params) {
1.6 paf 351: Pool& pool=r.pool();
352:
1.17 paf 353: Value& vfile_name=params->get_no_junction(0, "file name must not be code");
1.6 paf 354: const String& file_name=vfile_name.as_string();
355:
1.16 paf 356: gdImage& image=*load(r, method_name, file_name);
357: int width=image.SX();
358: int height=image.SY();
359: static_cast<VImage *>(r.self)->set(&file_name, width, height, &image);
1.6 paf 360: }
361:
1.21 paf 362: /** ^image.create[width;height] bgcolor=white
363: ^image.create[width;height;bgcolor]
364: */
1.17 paf 365: static void _create(Request& r, const String& method_name, MethodParams *params) {
1.6 paf 366: Pool& pool=r.pool();
367:
1.17 paf 368: int width=(int)r.process(params->get(0)).as_double();
369: int height=(int)r.process(params->get(1)).as_double();
1.8 paf 370: int bgcolor_value=0xffFFff;
1.6 paf 371: if(params->size()>2)
1.17 paf 372: bgcolor_value=(int)r.process(params->get(2)).as_double();
1.15 paf 373: gdImage& image=*new(pool) gdImage(pool);
374: image.Create(width, height);
375: image.FilledRectangle(0, 0, width-1, height-1, image.Color(bgcolor_value));
376: static_cast<VImage *>(r.self)->set(0, width, height, &image);
1.6 paf 377: }
378:
379: /// ^image.gif[]
1.17 paf 380: static void _gif(Request& r, const String& method_name, MethodParams *params) {
1.6 paf 381: Pool& pool=r.pool();
382:
1.9 paf 383: gdImage *image=static_cast<VImage *>(r.self)->image;
1.8 paf 384: if(!image)
1.16 paf 385: PTHROW(0, 0,
386: &method_name,
1.12 paf 387: "does not contain an image");
1.6 paf 388:
389: // could _ but don't thing it's wise to use $image.src for vfile.name
1.10 paf 390:
1.16 paf 391: String out(pool); image->Gif(out);
1.6 paf 392:
393: VFile& vfile=*new(pool) VFile(pool);
394: String& image_gif=*new(pool) String(pool, "image/gif");
1.20 paf 395: vfile.set(false/*not tainted*/,
396: out.cstr(String::UL_AS_IS), out.size(), 0, &image_gif);
1.6 paf 397:
398: r.write_no_lang(vfile);
399: }
400:
1.12 paf 401: /// ^image.line(x0;y0;x1;y1;color)
1.17 paf 402: static void _line(Request& r, const String& method_name, MethodParams *params) {
1.12 paf 403: Pool& pool=r.pool();
404:
405: gdImage *image=static_cast<VImage *>(r.self)->image;
406: if(!image)
1.16 paf 407: PTHROW(0, 0,
408: &method_name,
1.12 paf 409: "does not contain an image");
410:
411: image->Line(
1.17 paf 412: (int)r.process(params->get(0)).as_double(),
413: (int)r.process(params->get(1)).as_double(),
414: (int)r.process(params->get(2)).as_double(),
415: (int)r.process(params->get(3)).as_double(),
416: image->Color((int)r.process(params->get(4)).as_double()));
1.13 paf 417: }
418:
419: /// ^image.fill(x;y;color)
1.17 paf 420: static void _fill(Request& r, const String& method_name, MethodParams *params) {
1.13 paf 421: Pool& pool=r.pool();
422:
423: gdImage *image=static_cast<VImage *>(r.self)->image;
424: if(!image)
1.16 paf 425: PTHROW(0, 0,
426: &method_name,
1.13 paf 427: "does not contain an image");
1.12 paf 428:
1.13 paf 429: image->Fill(
1.17 paf 430: (int)r.process(params->get(0)).as_double(),
431: (int)r.process(params->get(1)).as_double(),
432: image->Color((int)r.process(params->get(2)).as_double()));
1.13 paf 433: }
434:
435: /// ^image.rectangle(x0;y0;x1;y1;color)
1.17 paf 436: static void _rectangle(Request& r, const String& method_name, MethodParams *params) {
1.13 paf 437: Pool& pool=r.pool();
438:
439: gdImage *image=static_cast<VImage *>(r.self)->image;
440: if(!image)
1.16 paf 441: PTHROW(0, 0,
442: &method_name,
1.13 paf 443: "does not contain an image");
444:
445: image->Rectangle(
1.17 paf 446: (int)r.process(params->get(0)).as_double(),
447: (int)r.process(params->get(1)).as_double(),
448: (int)r.process(params->get(2)).as_double(),
449: (int)r.process(params->get(3)).as_double(),
450: image->Color((int)r.process(params->get(4)).as_double()));
1.13 paf 451: }
452:
453: /// ^image.bar(x0;y0;x1;y1;color)
1.17 paf 454: static void _bar(Request& r, const String& method_name, MethodParams *params) {
1.13 paf 455: Pool& pool=r.pool();
456:
457: gdImage *image=static_cast<VImage *>(r.self)->image;
458: if(!image)
1.16 paf 459: PTHROW(0, 0,
460: &method_name,
1.13 paf 461: "does not contain an image");
462:
463: image->FilledRectangle(
1.17 paf 464: (int)r.process(params->get(0)).as_double(),
465: (int)r.process(params->get(1)).as_double(),
466: (int)r.process(params->get(2)).as_double(),
467: (int)r.process(params->get(3)).as_double(),
468: image->Color((int)r.process(params->get(4)).as_double()));
1.13 paf 469: }
470:
471: /// ^image.replace(color-source;color-dest)(x;y)... point coord pairs
1.17 paf 472: static void _replace(Request& r, const String& method_name, MethodParams *params) {
1.13 paf 473: Pool& pool=r.pool();
474:
475: gdImage *image=static_cast<VImage *>(r.self)->image;
476: if(!image)
1.16 paf 477: PTHROW(0, 0,
478: &method_name,
1.13 paf 479: "does not contain an image");
480:
481: if((params->size()-2)%2) // I see your thoughts, but that's more readable
1.16 paf 482: PTHROW(0, 0,
483: &method_name,
1.13 paf 484: "y coordinate missing");
485:
486: int n=(params->size()-2)/2;
487:
488: gdImage::Point *p=(gdImage::Point *)pool.malloc(sizeof(gdImage::Point)*n);
489: for(int i=0; i<n; i++) {
1.17 paf 490: p[i].x=(int)r.process(params->get(2+i*2+0)).as_double();
491: p[i].y=(int)r.process(params->get(2+i*2+1)).as_double();
1.13 paf 492: }
1.16 paf 493: image->FilledPolygonReplaceColor(p, n,
1.17 paf 494: image->Color((int)r.process(params->get(0)).as_double()), // src color
495: image->Color((int)r.process(params->get(1)).as_double()));// dest color
1.13 paf 496: }
497:
498: /// ^image.polygon(color)(x;y)... point coord pairs
1.17 paf 499: static void _polygon(Request& r, const String& method_name, MethodParams *params) {
1.13 paf 500: Pool& pool=r.pool();
501:
502: gdImage *image=static_cast<VImage *>(r.self)->image;
503: if(!image)
1.16 paf 504: PTHROW(0, 0,
505: &method_name,
1.13 paf 506: "does not contain an image");
507:
508: if((params->size()-1)%2) // [I see..] see now?
1.16 paf 509: PTHROW(0, 0,
510: &method_name,
1.13 paf 511: "y coordinate missing");
512:
513: int n=(params->size()-1)/2;
514:
515: gdImage::Point *p=(gdImage::Point *)pool.malloc(sizeof(gdImage::Point)*n);
516: for(int i=0; i<n; i++) {
1.17 paf 517: p[i].x=(int)r.process(params->get(1+i*2+0)).as_double();
518: p[i].y=(int)r.process(params->get(1+i*2+1)).as_double();
1.13 paf 519: }
1.16 paf 520: image->Polygon(p, n,
1.17 paf 521: image->Color((int)r.process(params->get(0)).as_double()));
1.13 paf 522: }
523:
524: /// ^image.polybar(color)(x;y)... point coord pairs
1.17 paf 525: static void _polybar(Request& r, const String& method_name, MethodParams *params) {
1.13 paf 526: Pool& pool=r.pool();
527:
528: gdImage *image=static_cast<VImage *>(r.self)->image;
529: if(!image)
1.16 paf 530: PTHROW(0, 0,
531: &method_name,
1.13 paf 532: "does not contain an image");
533:
534: if((params->size()-1)%2) // [I see..] see now?
1.16 paf 535: PTHROW(0, 0,
536: &method_name,
1.13 paf 537: "y coordinate missing");
538:
539: int n=(params->size()-1)/2;
540:
541: gdImage::Point *p=(gdImage::Point *)pool.malloc(sizeof(gdImage::Point)*n);
542: for(int i=0; i<n; i++) {
1.17 paf 543: p[i].x=(int)r.process(params->get(1+i*2+0)).as_double();
544: p[i].y=(int)r.process(params->get(1+i*2+1)).as_double();
1.13 paf 545: }
1.16 paf 546: image->FilledPolygon(p, n,
1.17 paf 547: image->Color((int)r.process(params->get(0)).as_double()));
1.12 paf 548: }
549:
1.16 paf 550: // font
551:
552: #define Y(y)(y+index*height+1)
1.21 paf 553:
554: /// simple gdImage-based font storage & text output
1.16 paf 555: class Font : public Pooled {
556: public:
557:
558: int height; /* Font heigth */
559: int space; /* Default char width */
560: gdImage& ifont;
561: const String& alphabet;
562:
563: Font(Pool& pool,
564: const String& aalphabet,
565: gdImage& aifont, int aheight, int aspace) : Pooled(pool),
566: alphabet(aalphabet),
567: height(aheight), space(aspace),
568: ifont(aifont) {
569: }
570:
571: /* ******************************** char ********************************** */
572:
573: int index_of(char ch) {
574: if(ch==' ') return -1;
575: return alphabet.pos(&ch, 1);
576: }
577:
578: int index_width(int index) {
579: if(index<0)
580: index=index_of('.');
581: if(index<0)
582: return 0;
583: int tr=ifont.GetTransparent();
584: for(int x=ifont.SX()-1; x>0; x--) {
585: for(int y=0; y<height-1; y++)
586: if(ifont.GetPixel(x, Y(y))!=tr)
587: return x+2;
588: }
589: return 0;
590: }
591:
592: void index_display(gdImage& image, int x, int y, int index){
593: if(index>=0)
594: ifont.Copy(image, x, y, 0, Y(0), index_width(index), height-1);
595: }
596:
597: /* ******************************** string ********************************** */
598: /*
599: int string_width(const char *cstr){
600: int result=0;
601: for(; *cstr; cstr++)
602: result+=index_width(index_of(*cstr));
603: return result;
604: }
605: */
606:
607: void string_display(gdImage& image, int x, int y, const String& s){
608: const char *cstr=s.cstr(String::UL_AS_IS);
609: if(cstr) for(; *cstr; cstr++) {
610: int index=index_of(*cstr);
611: index_display(image, x, y, index);
612: x+=space ? space : index_width(index);
613: }
614: }
615:
616: };
1.19 paf 617: /**
618: ^image.font[alPHAbet;font-file-name.gif](height)
619: ^image.font[alPHAbet;font-file-name.gif](height;width)
620: */
1.17 paf 621: static void _font(Request& r, const String& method_name, MethodParams *params) {
1.16 paf 622: Pool& pool=r.pool();
623:
1.17 paf 624: Value& valphabet=params->get_no_junction(0, "alphabet must not be code");
625: Value& file_name=params->get_no_junction(1, "file_name must not be code");
626: int height=(int)r.process(params->get(2)).as_double();
1.16 paf 627:
1.17 paf 628: int width=params->size()>3?(int)r.process(params->get(3)).as_double():0;
1.16 paf 629:
630: static_cast<VImage *>(r.self)->font=new(pool) Font(pool,
631: valphabet.as_string(),
632: *load(r, method_name, file_name.as_string()),
633: height, width);
634: }
635:
636: /// ^image.text(x;y)[text]
1.17 paf 637: static void _text(Request& r, const String& method_name, MethodParams *params) {
1.16 paf 638: Pool& pool=r.pool();
639:
1.17 paf 640: int x=(int)r.process(params->get(0)).as_double();
641: int y=(int)r.process(params->get(1)).as_double();
642: const String& s=r.process(params->get(2)).as_string();
1.16 paf 643:
644: VImage& vimage=*static_cast<VImage *>(r.self);
645: if(vimage.image)
646: if(vimage.font)
647: vimage.font->string_display(*vimage.image, x, y, s);
648: else
649: PTHROW(0, 0,
650: &method_name,
651: "set the font first");
652: else
653: PTHROW(0, 0,
654: &method_name,
655: "does not contain an image");
656: }
657:
1.22 ! paf 658: // constructor
! 659:
! 660: MImage::MImage(Pool& apool) : Methoded(apool) {
! 661: set_name(*NEW String(pool(), IMAGE_CLASS_NAME));
! 662:
! 663:
1.1 paf 664: // ^image:measure[DATA]
1.22 ! paf 665: add_native_method("measure", Method::CT_DYNAMIC, _measure, 1, 1);
1.3 paf 666:
667: /// ^image.html[]
668: /// ^image.html[hash]
1.22 ! paf 669: add_native_method("html", Method::CT_DYNAMIC, _html, 0, 1);
1.6 paf 670:
671: /// ^image.load[background.gif]
1.22 ! paf 672: add_native_method("load", Method::CT_DYNAMIC, _load, 1, 1);
1.6 paf 673:
674: /// ^image.create[width;height] bgcolor=white
675: /// ^image.create[width;height;bgcolor]
1.22 ! paf 676: add_native_method("create", Method::CT_DYNAMIC, _create, 2, 3);
1.6 paf 677:
678: /// ^image.gif[]
1.22 ! paf 679: add_native_method("gif", Method::CT_DYNAMIC, _gif, 0, 0);
1.12 paf 680:
681: /// ^image.line(x0;y0;x1;y1;color)
1.22 ! paf 682: add_native_method("line", Method::CT_DYNAMIC, _line, 5, 5);
1.13 paf 683:
684: /// ^image.fill(x;y;color)
1.22 ! paf 685: add_native_method("fill", Method::CT_DYNAMIC, _fill, 3, 3);
1.13 paf 686:
687: /// ^image.rectangle(x0;y0;x1;y1;color)
1.22 ! paf 688: add_native_method("rectangle", Method::CT_DYNAMIC, _rectangle, 5, 5);
1.13 paf 689:
690: /// ^image.bar(x0;y0;x1;y1;color)
1.22 ! paf 691: add_native_method("bar", Method::CT_DYNAMIC, _bar, 5, 5);
1.13 paf 692:
693: /// ^image.replace(color-source;color-dest)(x;y)... point coord pairs
1.22 ! paf 694: add_native_method("replace", Method::CT_DYNAMIC, _replace, 2+3*2, 2+100*2);
1.13 paf 695:
696: /// ^image.polygon(color)(x;y)... point coord pairs
1.22 ! paf 697: add_native_method("polygon", Method::CT_DYNAMIC, _polygon, 1+3*2, 1+100*2);
1.13 paf 698:
699: /// ^image.polybar(color)(x;y)... point coord pairs
1.22 ! paf 700: add_native_method("polybar", Method::CT_DYNAMIC, _polybar, 1+3*2, 1+100*2);
1.13 paf 701:
1.16 paf 702: /// ^image.font[alPHAbet;font-file-name.gif](height)
703: /// ^image.font[alPHAbet;font-file-name.gif](height;width)
1.22 ! paf 704: add_native_method("font", Method::CT_DYNAMIC, _font, 3, 4);
1.16 paf 705:
706: /// ^image.text(x;y)[text]
1.22 ! paf 707: add_native_method("text", Method::CT_DYNAMIC, _text, 3, 3);
1.16 paf 708:
1.22 ! paf 709: }
! 710:
! 711: // global variable
! 712:
! 713: Methoded *image_class;
! 714:
! 715: // creator
! 716:
! 717: Methoded *MImage_create(Pool& pool) {
! 718: return image_class=new(pool) MImage(pool);
1.1 paf 719: }
E-mail: