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