b9de771999-05-19Peter Bortas constant cvs_version="$Id: graphic_text.pike,v 1.161 1999/05/19 01:33:35 peter Exp $";
85e8321997-08-31Peter Bortas constant thread_safe=1;
ebf60d1997-03-08Henrik Grubbström (Grubba) 
a3605a1999-03-12Martin Stjernholm #include <config.h>
d47cbf1996-12-02Per Hedbor #include <module.h>
e5bad21998-02-10Per Hedbor #include <stat.h>
d47cbf1996-12-02Per Hedbor inherit "module"; inherit "roxenlib";
3992de1997-09-28Henrik Grubbström (Grubba) #ifndef VAR_MORE #define VAR_MORE 0 #endif /* VAR_MORE */
d47cbf1996-12-02Per Hedbor array register_module() {
b9de771999-05-19Peter Bortas  return ({ MODULE_PARSER,
5670551998-06-09Peter Bortas  "Graphics text", "Generates graphical texts.<p>" "See <tt>&lt;gtext help&gt;&lt;/gtext&gt;</tt> for "
b9de771999-05-19Peter Bortas  "more information.",
5670551998-06-09Peter Bortas  0, 1 });
0a76aa1998-03-27David Hedbor }
d47cbf1996-12-02Per Hedbor void create() {
39af1a1998-08-26Per Hedbor  defvar("colorparse", 1, "Parse tags for document colors", TYPE_FLAG, "If set, parse the specified tags for document colors.");
c97c421998-08-20Per Hedbor  defvar("colorparsing", ({"body", "td", "layer", "ilayer", "table"}), "Tags to parse for color", TYPE_STRING_LIST, "Which tags should be parsed for document colors? " "This will affect documents without gtext as well as documents " "with it, the parsing time is relative to the number of parsed " "tags in a document. You have to reload this module or restart "
39af1a1998-08-26Per Hedbor  "roxen for changes of this variable to take effect.", 0, lambda(){return !query("colorparse");});
c97c421998-08-20Per Hedbor  defvar("colormode", 1, "Normalize colors in parsed tags", TYPE_FLAG, "If set, replace 'roxen' colors (@c,m,y,k etc) with "
39af1a1998-08-26Per Hedbor  "'netscape' colors (#rrggbb). Setting this to off will lessen the "
c97c421998-08-20Per Hedbor  "performance impact of the 'Tags to parse for color' option quite"
39af1a1998-08-26Per Hedbor  " dramatically. You can try this out with the &lt;gauge&gt; tag.", 0, lambda(){return !query("colorparse");});
c97c421998-08-20Per Hedbor 
9b9f701997-08-12Per Hedbor  defvar("deflen", 300, "Default maximum text-length", TYPE_INT|VAR_MORE,
bfc7071997-01-13Per Hedbor  "The module will, per default, not try to render texts " "longer than this. This is a safeguard for things like " "&lt;gh1&gt;&lt;/gh&gt;, which would otherwise parse the" " whole document. This can be overrided with maxlen=... in the " "tag.");
b9de771999-05-19Peter Bortas  defvar("gif", 0, "Append .fmt (gif, jpeg etc) to all images", TYPE_FLAG|VAR_MORE, "Append .gif, .png, .gif etc to all images made by gtext. " "Normally this will only waste bandwidth");
d47cbf1996-12-02Per Hedbor }
c97c421998-08-20Per Hedbor static private mapping cached_args = ([ ]);
d47cbf1996-12-02Per Hedbor 
0a76aa1998-03-27David Hedbor #define MAX(a,b) ((a)<(b)?(b):(a)) static private mapping (int:array(array(int))) matrixes = ([]); array (array(int)) make_matrix(int size) { if(matrixes[size]) return matrixes[size]; array res; int i; int j; res = Array.map(allocate(size), lambda(int s, int size){ return allocate(size); }, size); for(i=0; i<size; i++) for(j=0; j<size; j++) res[i][j] = (int)MAX((float)size/2.0-sqrt((size/2-i)*(size/2-i) + (size/2-j)*(size/2-j)),0); return matrixes[size] = res; } object blur(object img, int amnt) { img->setcolor(0,0,0); img = img->autocrop(amnt, 0,0,0,0, 0,0,0); for(int i=0; i<amnt; i++) img = img->apply_matrix( make_matrix((int)sqrt(img->ysize()+20))); return img; } object outline(object on, object with, array (int) color, int radie, int x, int y) { int steps=10; for(int j=0; j<=steps; j++) on->paste_alpha_color(with, @color, (int)(0.5+x-(sin((float)j/steps*3.145*2)*radie)), (int)(0.5+y-(cos((float)j/steps*3.145*2)*radie))); return on; }
b9de771999-05-19Peter Bortas constant white = ({ 255,255,255 }); constant lgrey = ({ 200,200,200 }); constant grey = ({ 128,128,128 }); constant black = ({ 0,0,0 }); constant wwwb = ({ lgrey,lgrey,grey,black });
0a76aa1998-03-27David Hedbor  object bevel(object in, int width, int|void invert) { int h=in->ysize(); int w=in->xsize(); object corner = Image.image(width+1,width+1); object corner2 = Image.image(width+1,width+1); object pix = Image.image(1,1); for(int i=-1; i<=width; i++) { corner->line(i,width-i,i,-1, @white); corner2->setpixel(width-i, width-i, @white); in->paste_alpha(pix, 185, w - width + i+1, h - width + i+1); } if(!invert) { in->paste_alpha(Image.image(width,h-width*2,@white), 160, 0, width); in->paste_alpha(Image.image(width,h-width*2,@black), 128, in->xsize()-width, width); in->paste_alpha(Image.image(w-width,width,@white), 160, 0, 0); in->paste_alpha(Image.image(w-width,width,@black), 128, width, in->ysize()-width); } else { corner=corner->invert(); corner2=corner2->invert(); in->paste_alpha(Image.image(width,h-width*2,@black), 160, 0, width); in->paste_alpha(Image.image(width,h-width*2,@white), 128, in->xsize()-width, width); in->paste_alpha(Image.image(w-width,width,@black), 160, 0, 0); in->paste_alpha(Image.image(w-width,width,@white), 128, width, in->ysize()-width); } in->paste_mask(corner, corner->color(95,95,95), in->xsize()-width,-1); in->paste_mask(corner, corner->invert()->color(128,128,128), in->xsize()-width,-1); in->paste_mask(corner, corner->color(95,95,95), -1, in->ysize()-width); in->paste_mask(corner, corner->invert()->color(128,128,128), -1, in->ysize()-width); corner=0; in->paste_mask(corner2, corner2->color(70,70,70), -1, -1); corner2 = pix = 0; return in; } object make_text_image(mapping args, object font, string text,object id) {
b9de771999-05-19Peter Bortas  // object text_alpha=font->write(@(text/"\n")); object text_alpha=font->write(@(args->encoding? (Locale.Charset.decoder(args->encoding)-> feed(text)->drain())/"\n" : text/"\n"));
0a76aa1998-03-27David Hedbor  int xoffset=0, yoffset=0; if(!text_alpha->xsize() || !text_alpha->ysize()) text_alpha = Image.image(10,10, 0,0,0); // perror("Making image of '%s', args=%O\n", text, args); if(int op=((((int)args->opaque)*255)/100)) // Transparent text... text_alpha=text_alpha->color(op,op,op); int txsize=text_alpha->xsize(); int tysize=text_alpha->ysize(); // Size of the text, in pixels. int xsize=txsize; // image size, in pixels int ysize=tysize; // perror("Xsize=%d; ysize=%d\n",xsize,ysize); if(args->bevel) { xoffset += (int)args->bevel; yoffset += (int)args->bevel; xsize += ((int)args->bevel)*2; ysize += ((int)args->bevel)*2; } if(args->spacing) { xoffset += (int)args->spacing; yoffset += (int)args->spacing; xsize += ((int)args->spacing)*2; ysize += ((int)args->spacing)*2; } if(args->yspacing) { yoffset += (int)args->yspacing; ysize += ((int)args->yspacing)*2; } if(args->shadow) { xsize+=((int)(args->shadow/",")[-1])+2; ysize+=((int)(args->shadow/",")[-1])+2; } if(args->bshadow) { xsize+=(int)args->bshadow+3; ysize+=(int)args->bshadow+3; } if(args->fadein) { xsize+=6; ysize+=6; xoffset+=3; yoffset+=3; } if(args->move) { int dx,dy; sscanf(args->move, "%d,%d", dx, dy); xoffset += dx; yoffset += dy; } if(args->ghost) { int howmuch=(int)args->ghost; xsize+=howmuch*2+10; xoffset += 3; ysize+=howmuch*2+10; } if(args->xspacing) { xoffset += (int)args->xspacing; xsize += ((int)args->xspacing)*2; } if(args->border) { xoffset += (int)args->border; yoffset += (int)args->border; xsize += ((int)args->border)*2; ysize += ((int)args->border)*2; } array (int) bgcolor = parse_color(args->bg); array (int) fgcolor = parse_color(args->fg); object background,foreground;
a2d2ca1999-05-18Peter Bortas  if(args->texture) { object t = roxen.load_image(args->texture,id); if( t )
0a76aa1998-03-27David Hedbor  {
a2d2ca1999-05-18Peter Bortas  foreground = t; if(args->tile)
0a76aa1998-03-27David Hedbor  {
a2d2ca1999-05-18Peter Bortas  object b2 = Image.image(xsize,ysize); for(int x=0; x<xsize; x+=foreground->xsize()) for(int y=0; y<ysize; y+=foreground->ysize())
0a76aa1998-03-27David Hedbor  b2->paste(foreground, x, y);
a2d2ca1999-05-18Peter Bortas  foreground = b2; } else if(args->mirrortile) { object b2 = Image.image(xsize,ysize); object b3 = Image.image(foreground->xsize()*2,foreground->ysize()*2); b3->paste(foreground,0,0); b3->paste(foreground->mirrorx(),foreground->xsize(),0); b3->paste(foreground->mirrory(),0,foreground->ysize()); b3->paste(foreground->mirrorx()->mirrory(),foreground->xsize(), foreground->ysize()); foreground = b3; for(int x=0; x<xsize; x+=foreground->xsize()) { for(int y=0; y<ysize; y+=foreground->ysize()) if(y%2) b2->paste(foreground->mirrory(), x, y); else b2->paste(foreground, x, y); foreground = foreground->mirrorx(); } foreground = b2;
0a76aa1998-03-27David Hedbor  }
a2d2ca1999-05-18Peter Bortas  } else werror("Failed to load image for "+args->texture+"\n");
0a76aa1998-03-27David Hedbor  }
7b15a61998-08-10Johan Schön  int background_is_color; if(args->background &&
a2d2ca1999-05-18Peter Bortas  ((background = roxen.load_image(args->background, id)) ||
7b15a61998-08-10Johan Schön  (sizeof(args->background)>1 && (background=Image.image(xsize,ysize, @(parse_color(args->background[1..])))) && (background_is_color=1)))) { object alpha;
a2d2ca1999-05-18Peter Bortas  if(args->alpha && (alpha = roxen.load_image(args->alpha,id)) && background_is_color)
7b15a61998-08-10Johan Schön  { xsize=MAX(xsize,alpha->xsize()); ysize=MAX(ysize,alpha->ysize());
17bb761998-08-28Marcus Wellhardh  if((float)args->scale) alpha=alpha->scale(1/(float)args->scale);
7b15a61998-08-10Johan Schön  background=Image.image(xsize,ysize, @(parse_color(args->background[1..]))); }
dd8da81998-09-21Johan Schön  if((float)args->scale >= 0.1 && !alpha)
0a76aa1998-03-27David Hedbor  background = background->scale(1.0/(float)args->scale);
7b15a61998-08-10Johan Schön 
0a76aa1998-03-27David Hedbor  if(args->tile) { object b2 = Image.image(xsize,ysize); for(int x=0; x<xsize; x+=background->xsize()) for(int y=0; y<ysize; y+=background->ysize()) b2->paste(background, x, y); background = b2; } else if(args->mirrortile) { object b2 = Image.image(xsize,ysize); object b3 = Image.image(background->xsize()*2,background->ysize()*2); b3->paste(background,0,0); b3->paste(background->mirrorx(),background->xsize(),0); b3->paste(background->mirrory(),0,background->ysize()); b3->paste(background->mirrorx()->mirrory(),background->xsize(), background->ysize()); background = b3; for(int x=0; x<xsize; x+=background->xsize()) { for(int y=0; y<ysize; y+=background->ysize()) if(y%2) b2->paste(background->mirrory(), x, y); else b2->paste(background, x, y); background = background->mirrorx(); } background = b2; }
7b15a61998-08-10Johan Schön  xsize = MAX(xsize,background->xsize()); ysize = MAX(ysize,background->ysize());
7d92231998-08-10Johan Schön 
7b15a61998-08-10Johan Schön  if(alpha) background->paste_alpha_color(alpha->invert(),@bgcolor);
0a76aa1998-03-27David Hedbor  switch(lower_case(args->talign||"left")) { case "center": xoffset = (xsize/2 - txsize/2); yoffset = (ysize/2 - tysize/2); break; case "right": xoffset = (xsize - txsize); break; case "left": } } else background = Image.image(xsize, ysize, @bgcolor); if(args->border) { int b = (int)args->border; background->setcolor(@parse_color((args->border/",")[-1])); for(--b;b>=0;b--) { // upper left -- upper right background->line(b,b, xsize-b-1, b); // lower left -- lower right background->line(b,ysize-b-1, xsize-b-1, ysize-b-1); // upper left -- lower left background->line(b,b, b, ysize-b-1); // upper right -- lower right background->line(xsize-b-1,b, xsize-b-1, ysize-b-1); } } background->setcolor(@bgcolor); if(args->size || args->xsize || args->ysize) { int xs=background->xsize(), ys=background->ysize(); if(args->size) { xs=(int)args->size; ys=(int)(args->size/",")[-1]; } if(args->xsize) xs=(int)args->xsize; if(args->ysize) ys=(int)args->ysize;
0fa8b21998-07-04Peter Bortas  if(!args->rescale) background = background->copy(0,0,xs-1,ys-1); else background = background->scale(xs, ys);
0a76aa1998-03-27David Hedbor  } if(args->turbulence) { array (float|array(int)) arg=({}); foreach((args->turbulence/";"), string s) { array q= s/","; if(sizeof(q)<2) args+=({ ((float)s)||0.2, ({ 255,255,255 }) }); arg+=({ ((float)q[0])||0.2, parse_color(q[1]) }); } background=background->turbulence(arg); } if(args->bevel) background = bevel(background,(int)args->bevel,!!args->pressed); if(args->textbox) // Draw a text-box on the background. { int alpha,border; string bg; sscanf(args->textbox, "%d,%s", alpha, bg); sscanf(bg,"%s,%d", bg,border); background->paste_alpha(Image.image(txsize+border*2,tysize+border*2, @parse_color(bg)), 255-(alpha*255/100),xoffset-border,yoffset-border); } if(args->ghost) { // Francesco..
f08b991999-01-25Henrik Grubbström (Grubba)  array(string) a = (args->ghost/","); if (sizeof(a) < 2) { // Bad argument. } else { int sdist = (int)(a[0]); int bl=(int)(a[1]); array(int)clr=parse_color(a[-1]); int j; object ta = text_alpha->copy(); for (j=0;j<bl;j++) ta=ta->apply_matrix(({ ({6,7,7,7,6}),({7,8,8,8,7}),({7,8,8,8,7}),({7,8,8,8,7}),({6,7,7,7,6}) })); background->paste_alpha_color(ta,@clr,xoffset+sdist,yoffset+sdist); fgcolor=bgcolor; }
0a76aa1998-03-27David Hedbor  } if(args->shadow) { int sd = ((int)args->shadow+10)*2; int sdist = ((int)(args->shadow/",")[-1])+2; object ta = text_alpha->copy(); ta = ta->color(256-sd,256-sd,256-sd); array sc = parse_color(args->scolor||"black"); background->paste_alpha_color(ta,sc[0],sc[1],sc[2], xoffset+sdist,yoffset+sdist); } #define MIN(x,y) ((x)<(y)?(x):(y)) if(args->bshadow) { int sdist = (int)(args->bshadow)+1; int xs,ys; xs = text_alpha->xsize()+sdist*2+4; ys = text_alpha->ysize()+sdist*2+4; object ta = Image.image(xs+sdist*2,ys+sdist*2); array sc = parse_color(args->scolor||"black"); ta->paste_alpha_color(text_alpha,255,255,255,sdist,sdist); ta = blur(ta, MIN((sdist/2),1))->color(256,256,256); background->paste_alpha_color(ta,sc[0],sc[1],sc[2], xoffset+sdist,yoffset+sdist); } if(args->glow) { int amnt = (int)(args->glow/",")[-1]+2; array (int) blurc = parse_color((args->glow/",")[0]); background->paste_alpha_color(blur(text_alpha, amnt),@blurc, xoffset-amnt, yoffset-amnt); } if(args->chisel) foreground=text_alpha->apply_matrix(({ ({8,1,0}), ({1,0,-1}), ({0,-1,-8}) }), 128,128,128, 15 ) ->color(@fgcolor); if(!foreground) foreground=Image.image(txsize, tysize, @fgcolor); if(args->textscale) { string c1="black",c2="black",c3="black",c4="black"; sscanf(args->textscale, "%s,%s,%s,%s", c1, c2, c3, c4); foreground->tuned_box(0,0, txsize,tysize, ({parse_color(c1),parse_color(c2),parse_color(c3), parse_color(c4)})); } if(args->outline) outline(background, text_alpha, parse_color((args->outline/",")[0]), ((int)(args->outline/",")[-1])+1, xoffset, yoffset);
0fa8b21998-07-04Peter Bortas  if(args->textbelow) { array color = parse_color(args->textbelow); // foreground = foreground->autocrop(); // text_alpha = text_alpha->autocrop(); background->setcolor( @color ); int oby = background->ysize(); background = background->copy(0,0, max(background->xsize()-1, foreground->xsize()-1), background->ysize()-1 +foreground->ysize()); background->paste_mask( foreground, text_alpha, (background->xsize()-foreground->xsize())/2, oby ); } else background->paste_mask(foreground, text_alpha, xoffset, yoffset);
0a76aa1998-03-27David Hedbor  foreground = text_alpha = 0;
b9de771999-05-19Peter Bortas  // handled by the image cache nowdays. :-) // if((float)args->scale>0.0) // if((float)args->scale <= 2.0) // background = background->scale((float)args->scale);
0a76aa1998-03-27David Hedbor  if(args->rotate) { string c; if(sscanf(args->rotate, "%*d,%s", c)==2) background->setcolor(@parse_color(c)); else background->setcolor(@bgcolor); background = background->rotate((float)args->rotate); } if(args->crop) background = background->autocrop(); return background; }
b9de771999-05-19Peter Bortas roxen.ImageCache image_cache;
e5bad21998-02-10Per Hedbor 
08df121997-08-19Henrik Grubbström (Grubba) void start(int|void val, object|void conf)
2468b21997-07-06Henrik Grubbström (Grubba) {
b9de771999-05-19Peter Bortas  image_cache = roxen.ImageCache( "gtext", draw_callback );
2468b21997-07-06Henrik Grubbström (Grubba) }
c3655b1997-01-27Per Hedbor 
b1ab8d1997-12-23Per Hedbor constant nbsp = iso88591["&nbsp;"]; constant replace_from = indices( iso88591 )+ ({"&ss;","&lt;","&gt;","&amp",}); constant replace_to = values( iso88591 ) + ({ nbsp, "<", ">", "&", }); #define simplify_text( from ) replace(from,replace_from,replace_to)
06583f1997-09-03Per Hedbor 
20ca2b1998-01-26Per Hedbor 
b9de771999-05-19Peter Bortas mixed draw_callback(mapping args, object id)
d47cbf1996-12-02Per Hedbor {
7faa951997-09-01Per Hedbor  array err;
420fd91998-02-27Per Hedbor  mixed data;
b9de771999-05-19Peter Bortas  int elapsed; string text = args->text; string orig_text = text; object img;
86352a1998-03-01Per Hedbor 
b9de771999-05-19Peter Bortas  m_delete( args, "text" ); if(!sizeof(args))
420fd91998-02-27Per Hedbor  {
b9de771999-05-19Peter Bortas  args=(["fg":"black","bg":"white","notrans":"1"]); text="Please reload this page";
420fd91998-02-27Per Hedbor  }
06e3e41998-08-14David Hedbor  //werror("Not cached: %O -> %O\n", key, text); //werror("In cache: %O\n", sort(indices(cache->cache)));
86352a1998-03-01Per Hedbor 
b9de771999-05-19Peter Bortas  if(!args->verbatim) // typographically correct...
ba73a21996-12-10Per Hedbor  {
b9de771999-05-19Peter Bortas  text = replace(text, nbsp, " "); text = simplify_text( text ); string res="",nspace="",cspace=""; foreach(text/"\n", string line)
06583f1997-09-03Per Hedbor  {
b9de771999-05-19Peter Bortas  cspace="";nspace=""; foreach(line/" ", string word)
06583f1997-09-03Per Hedbor  {
b9de771999-05-19Peter Bortas  string nonum; if(strlen(word) && (nonum = replace(word, ({"1","2","3","4","5","6","7","8","9","0","."}), ({"","","","","","","","","","",""}))) == "") { cspace=nbsp+nbsp; if((strlen(word)-strlen(nonum)<strlen(word)/2) && (upper_case(word) == word)) { word=((word/"")*nbsp); } } else if(cspace!="") { cspace=" "; } res+=(nspace==cspace?nspace:" ")+word; if(cspace!="") nspace=cspace; else nspace=" ";
06583f1997-09-03Per Hedbor  }
b9de771999-05-19Peter Bortas  res+="\n";
0a76aa1998-03-27David Hedbor  }
b9de771999-05-19Peter Bortas  text=replace(res[..strlen(res)-2], ({"!","?",": "}),({ nbsp+"!",nbsp+"?",nbsp+": "})); text=replace(replace(replace(text,({". ",". "+nbsp}), ({"\000","\001"})),".","."+nbsp+nbsp), ({"\000","\001"}),({". ","."+nbsp})); }
41d0f91998-02-20Per Hedbor 
b9de771999-05-19Peter Bortas  if( args->afont ) data = resolve_font(args->afont+" "+(args->font_size||32)); else
41d0f91998-02-20Per Hedbor  {
b9de771999-05-19Peter Bortas  if(!args->nfont) args->nfont = args->font; int bold, italic; if(args->bold) bold=1; if(args->light) bold=-1; if(args->black) bold=2; if(args->italic) italic=1; data = get_font(args->nfont||"default", (int)args->font_size||32,bold,italic, lower_case(args->talign||"left"), (float)(int)args->xpad, (float)(int)args->ypad);
41d0f91998-02-20Per Hedbor  }
9558e31998-07-04Per Hedbor 
b9de771999-05-19Peter Bortas  if (!data) error("gtext: No font!\n");
974b2a1997-10-02Peter Bortas 
b9de771999-05-19Peter Bortas  // Fonts and such are now initialized. img = make_text_image(args,data,text,id);
1a67581997-09-26Henrik Grubbström (Grubba) 
b9de771999-05-19Peter Bortas  // Now we have the image in 'img', or nothing.
9558e31998-07-04Per Hedbor 
b9de771999-05-19Peter Bortas  if( !args->scroll && !args->fadein ) { if(!args->notrans)
d47cbf1996-12-02Per Hedbor  {
b9de771999-05-19Peter Bortas  array (int) bgcolor = parse_color(args->bg); object alpha; alpha = img->distancesq( @bgcolor ); alpha->gamma( 8 ); return ([ "img":img, "alpha":alpha ]);
d47cbf1996-12-02Per Hedbor  }
b9de771999-05-19Peter Bortas  return img; }
c97c421998-08-20Per Hedbor 
b9de771999-05-19Peter Bortas  if(args->fadein)
68e0301997-08-19Per Hedbor  {
b9de771999-05-19Peter Bortas  int amount=2, steps=10, delay=10, initialdelay=0, ox; string res = img->gif_begin(); sscanf(args->fadein,"%d,%d,%d,%d", amount, steps, delay, initialdelay); if(initialdelay)
c97c421998-08-20Per Hedbor  {
b9de771999-05-19Peter Bortas  object foo=Image.image(img->xsize(),img->ysize(),@parse_color(args->bg)); res += foo->gif_add(0,0,initialdelay);
c97c421998-08-20Per Hedbor  }
b9de771999-05-19Peter Bortas  for(int i = 0; i<(steps-1); i++) { object foo=img->clone(); foo = foo->apply_matrix(make_matrix(( (int)((steps-i)*amount)))); res += foo->gif_add(0,0,delay);
c97c421998-08-20Per Hedbor  }
b9de771999-05-19Peter Bortas  res+= img->gif_add(0,0,delay); res += img->gif_end(); data = ({ res, ({ img->xsize(), img->ysize() }) });
4f57021997-09-03Henrik Grubbström (Grubba)  }
b9de771999-05-19Peter Bortas  else
814db51998-09-12Per Hedbor  {
b9de771999-05-19Peter Bortas  int len=100, steps=30, delay=5, ox; string res = img->gif_begin() + img->gif_netscape_loop(); sscanf(args->scroll, "%d,%d,%d", len, steps, delay); img=img->copy(0,0,(ox=img->xsize())+len-1,img->ysize()-1); img->paste(img, ox, 0); for(int i = 0; i<steps; i++) { int xp = i*ox/steps; res += img->copy(xp, 0, xp+len, img->ysize(), @parse_color(args->bg))->gif_add(0,0,delay); } res += img->gif_end(); data = ({ res, ({ len, img->ysize() }) });
814db51998-09-12Per Hedbor  }
68e0301997-08-19Per Hedbor 
b9de771999-05-19Peter Bortas  return ([ "data":data[0], "metadata": ([ "xsize":data[1][0], "ysize":data[1][1], "type":"image/gif", ]) ]);
68e0301997-08-19Per Hedbor }
b9de771999-05-19Peter Bortas mapping find_internal(string f, object rid)
d47cbf1996-12-02Per Hedbor {
b9de771999-05-19Peter Bortas  if( query("gif") && f[-4]=='.') // Remove .ext f = f[..strlen(f)-5]; return image_cache->http_file_answer( f, rid );
d47cbf1996-12-02Per Hedbor } string magic_javascript_header(object id) {
273a9a1997-10-17Johan Schön  if(!id->supports->netscape_javascript || !id->supports->images) return "";
d47cbf1996-12-02Per Hedbor  return
0943711997-02-25Per Hedbor  ("\n<script>\n"
e8790b1998-02-19Per Hedbor  "function i(ri,hi,txt)\n"
d47cbf1996-12-02Per Hedbor  "{\n"
0943711997-02-25Per Hedbor  " document.images[ri].src = hi.src;\n" " setTimeout(\"top.window.status = '\"+txt+\"'\", 100);\n"
d47cbf1996-12-02Per Hedbor  "}\n" "</script>\n");
6909c91997-09-22Johan Schön 
d47cbf1996-12-02Per Hedbor } string magic_image(string url, int xs, int ys, string sn, string image_1, string image_2, string alt,
dd8da81998-09-21Johan Schön  string mess,object id,string input,string extra_args,string lp)
d47cbf1996-12-02Per Hedbor {
dd8da81998-09-21Johan Schön  if(!id->supports->images) return (lp?lp:"")+alt+(lp?"</a>":"");
273a9a1997-10-17Johan Schön  if(!id->supports->netscape_javascript)
38dca81996-12-10Per Hedbor  return (!input)?
c97c421998-08-20Per Hedbor  ("<a "+extra_args+"href=\""+url+"\"><img src=\""+image_1+"\" name="+sn+" border=0 "+
704c361998-08-28Johan Schön  "alt=\""+alt+"\"></a>"):
f6d62d1997-03-26Per Hedbor  ("<input type=image "+extra_args+" src=\""+image_1+"\" name="+input+">");
d47cbf1996-12-02Per Hedbor  return ("<script>\n"
7f79ee1998-08-02Peter Bortas  " "+sn+"l = new Image("+xs+", "+ys+");"+sn+"l.src = \""+image_1+"\";\n" " "+sn+"h = new Image("+xs+", "+ys+");"+sn+"h.src = \""+image_2+"\";\n" "</script>\n"+
ca0f081997-02-22Per Hedbor  ("<a "+extra_args+"href=\""+url+"\" "+ (input?"onClick='document.forms[0].submit();' ":"")
e8790b1998-02-19Per Hedbor  +"onMouseover=\"i('"+sn+"',"+sn+"h,'"+(mess||url)+"'); return true;\"\n"
bf66201998-09-20David Hedbor  "onMouseout=\"top.window.status='';document.images['"+sn+"'].src = "+sn+"l.src;\"><img "
41d0f91998-02-20Per Hedbor  "width="+xs+" height="+ys+" src=\""+image_1+"\" name="+sn+
704c361998-08-28Johan Schön  " border=0 alt=\""+alt+"\" ></a>"));
d47cbf1996-12-02Per Hedbor }
b91fd51996-12-10Per Hedbor  string extra_args(mapping in) { string s=""; foreach(indices(in), string i) { switch(i) { case "target":
bfc7071997-01-13Per Hedbor  case "hspace": case "vspace": case "onclick":
b7ee571998-04-19Peter Bortas  case "class": case "id":
80739c1996-12-10Per Hedbor  s+=i+"='"+in[i]+"' ";
b91fd51996-12-10Per Hedbor  m_delete(in, i); break; } } return s; }
b9de771999-05-19Peter Bortas string tag_gtext_id(string t, mapping arg, string ctn,
07969c1997-02-25Per Hedbor  object id, object foo, mapping defines) { int short=!!arg->short;
fc57521998-03-06Per Hedbor  if(arg->help) return "Arguments are identical to the argumets to &lt;gtext&gt;. This tag returns a url-prefix that can be used to generate gtexts.";
07969c1997-02-25Per Hedbor  m_delete(arg, "short"); m_delete(arg, "maxlen"); m_delete(arg,"magic"); m_delete(arg,"submit"); extra_args(arg); m_delete(arg,"split"); if(defines->fg && !arg->fg) arg->fg=defines->fg; if(defines->bg && !arg->bg) arg->bg=defines->bg;
814db51998-09-12Per Hedbor  if(defines->nfont && !arg->nfont) arg->nfont=defines->nfont; if(defines->afont && !arg->afont) arg->afont=defines->afont; if(defines->font && !arg->font) arg->font=defines->font;
3a4d7e1997-09-03Per Hedbor 
c97c421998-08-20Per Hedbor  if(arg->background) arg->background = fix_relative(arg->background,id); if(arg->texture) arg->texture = fix_relative(arg->texture,id); if(arg->magic_texture) arg->magic_texture=fix_relative(arg->magic_texture,id); if(arg->magic_background) arg->magic_background=fix_relative(arg->magic_background,id); if(arg->magicbg) arg->magicbg = fix_relative(arg->magicbg,id); if(arg->alpha) arg->alpha = fix_relative(arg->alpha,id);
b9de771999-05-19Peter Bortas  arg->text = ctn;
07969c1997-02-25Per Hedbor  if(!short)
b9de771999-05-19Peter Bortas  return query_internal_location()+image_cache->store( arg, id );
07969c1997-02-25Per Hedbor  else
b9de771999-05-19Peter Bortas  return image_cache->store( arg, id );
07969c1997-02-25Per Hedbor }
62d8c41997-10-16Per Hedbor string tag_graphicstext(string t, mapping arg, string contents, object id, object foo, mapping defines) {
0d19e01998-07-06Peter Bortas  if((contents-" ")=="") return "";
62d8c41997-10-16Per Hedbor //Allow <accessed> and others inside <gtext>.
704c361998-08-28Johan Schön  if(arg->nowhitespace) { sscanf(contents,"%*[ \n\r\t]%s",contents); sscanf(reverse(contents),"%*[ \n\r\t]%s",contents); contents=reverse(contents); }
b9de771999-05-19Peter Bortas  if(arg->help)
fc57521998-03-06Per Hedbor  return "This tag calls &lt;gtext&gt; with different default values.";
41d0f91998-02-20Per Hedbor  if(arg->background) arg->background = fix_relative(arg->background,id); if(arg->texture) arg->texture = fix_relative(arg->texture,id); if(arg->magic_texture) arg->magic_texture=fix_relative(arg->magic_texture,id); if(arg->magic_background) arg->magic_background=fix_relative(arg->magic_background,id); if(arg->magicbg) arg->magicbg = fix_relative(arg->magicbg,id);
7b15a61998-08-10Johan Schön  if(arg->alpha) arg->alpha = fix_relative(arg->alpha,id);
41d0f91998-02-20Per Hedbor 
974b2a1997-10-02Peter Bortas  string gif="";
62d8c41997-10-16Per Hedbor  if(query("gif")) gif=".gif";
974b2a1997-10-02Peter Bortas 
033c7e1997-02-27Per Hedbor #if efun(_static_modules) contents = parse_rxml(contents, id, foo, defines); #else contents = parse_rxml(contents, id, foo); #endif
62d8c41997-10-16Per Hedbor  string lp, url, ea;
d47cbf1996-12-02Per Hedbor  string pre, post, defalign, gt, rest, magic;
1bd5c91997-09-26Henrik Grubbström (Grubba)  int i; string split;
d47cbf1996-12-02Per Hedbor 
bfc7071997-01-13Per Hedbor  contents = contents[..((int)arg->maxlen||QUERY(deflen))]; m_delete(arg, "maxlen");
d47cbf1996-12-02Per Hedbor  if(arg->magic) {
d23e421997-05-08Per Hedbor  magic=replace(arg->magic,"'","`");
d47cbf1996-12-02Per Hedbor  m_delete(arg,"magic"); }
38dca81996-12-10Per Hedbor  int input; if(arg->submit) { input=1; m_delete(arg,"submit"); }
d47cbf1996-12-02Per Hedbor 
bfc7071997-01-13Per Hedbor 
80739c1996-12-10Per Hedbor  ea = extra_args(arg);
bfc7071997-01-13Per Hedbor 
0943711997-02-25Per Hedbor  // Modify the 'arg' mapping...
d47cbf1996-12-02Per Hedbor  if(arg->href) { url = arg->href;
80739c1996-12-10Per Hedbor  lp = "<a href=\""+arg->href+"\" "+ea+">";
d47cbf1996-12-02Per Hedbor  if(!arg->fg) arg->fg=defines->link||"#0000ff";
0943711997-02-25Per Hedbor  m_delete(arg, "href");
d47cbf1996-12-02Per Hedbor  } if(defines->fg && !arg->fg) arg->fg=defines->fg; if(defines->bg && !arg->bg) arg->bg=defines->bg;
814db51998-09-12Per Hedbor  if(defines->nfont && !arg->nfont) arg->nfont=defines->nfont; if(defines->afont && !arg->afont) arg->afont=defines->afont; if(defines->font && !arg->font) arg->font=defines->font; if(defines->bold && !arg->bold) arg->bold=defines->bold; if(defines->italic && !arg->italic) arg->italic=defines->italic; if(defines->black && !arg->black) arg->black=defines->black; if(defines->narrow && !arg->narrow) arg->narrow=defines->narrow;
d47cbf1996-12-02Per Hedbor  if(arg->split) {
f1be801998-02-22Per Hedbor  if (sizeof(split=arg->split) != 1)
1bd5c91997-09-26Henrik Grubbström (Grubba)  split = " ";
d47cbf1996-12-02Per Hedbor  m_delete(arg,"split"); } // Support for <gh 2> like things. for(i=2; i<10; i++) if(arg[(string)i]) { arg->scale = 1.0 / ((float)i*0.6); m_delete(arg, (string)i);
9d16ce1997-03-01Per Hedbor  break;
d47cbf1996-12-02Per Hedbor  } // Support for <gh1> like things. if(sscanf(t, "%s%d", t, i)==2) if(i > 1) arg->scale = 1.0 / ((float)i*0.6);
0943711997-02-25Per Hedbor  string na = arg->name, al=arg->align; m_delete(arg, "name"); m_delete(arg, "align");
d47cbf1996-12-02Per Hedbor 
b9de771999-05-19Peter Bortas  // Now the 'arg' mapping is modified enough..
d47cbf1996-12-02Per Hedbor  gt=contents; rest="";
f6d62d1997-03-26Per Hedbor  switch(t) { case "gh1": case "gh2": case "gh3": case "gh4": case "gh5": case "gh6": case "gh7": case "gh": pre="<p>"; post="<br>"; defalign="top"; break; case "gtext": pre=""; post=""; defalign="bottom"; break; case "anfang": gt=contents[0..0]; rest=contents[1..]; pre="<br clear=left>"; post=""; defalign="left"; break; }
d47cbf1996-12-02Per Hedbor  if(split) { string word;
bfb80b1997-09-26Henrik Grubbström (Grubba)  array res = ({ pre });
d47cbf1996-12-02Per Hedbor  if(lp) res+=({ lp }); gt=replace(gt, "\n", " ");
b9de771999-05-19Peter Bortas  foreach(gt/split-({""}), word)
d47cbf1996-12-02Per Hedbor  {
b9de771999-05-19Peter Bortas  arg->text = word; string fn = image_cache->store( arg ); mapping size = image_cache->metadata( fn, id, 1 ); mapping tag = ([ "alt":(arg->alt||word), "src":query_internal_location()+fn+gif, ]); if( size ) { tag->width = size->xsize; tag->height = size->ysize;
1bd5c91997-09-26Henrik Grubbström (Grubba)  }
b9de771999-05-19Peter Bortas  res += ({ make_tag( "img", tag )+" " });
d47cbf1996-12-02Per Hedbor  }
bfb80b1997-09-26Henrik Grubbström (Grubba)  if(lp) res += ({ "</a>"+post });
d47cbf1996-12-02Per Hedbor  return res*""; }
b9de771999-05-19Peter Bortas  arg->text = gt; string num = image_cache->store( arg ); mapping size = image_cache->metadata( arg, id, 1 );
f1be801998-02-22Per Hedbor 
d47cbf1996-12-02Per Hedbor  if(magic) { string res = "";
bfc7071997-01-13Per Hedbor  if(!arg->fg) arg->fg=defines->link||"#0000ff";
d47cbf1996-12-02Per Hedbor  arg = mkmapping(indices(arg), values(arg));
bfc7071997-01-13Per Hedbor  if(arg->fuzz) if(arg->fuzz != "fuzz") arg->glow = arg->fuzz; else arg->glow = arg->fg;
d47cbf1996-12-02Per Hedbor  arg->fg = defines->alink||"#ff0000";
9f67f31997-10-27Per Hedbor  if(arg->magicbg) arg->background = arg->magicbg;
38dca81996-12-10Per Hedbor  if(arg->bevel) arg->pressed=1;
0943711997-02-25Per Hedbor 
20ca2b1998-01-26Per Hedbor  foreach(glob("magic_*", indices(arg)), string q) { arg[q[6..]]=arg[q]; m_delete(arg, q); }
b9de771999-05-19Peter Bortas  string num2 = image_cache->store( arg ); size = image_cache->metadata( arg, id );
0943711997-02-25Per Hedbor 
b9de771999-05-19Peter Bortas  if(!defines->magic_java) res = magic_javascript_header(id);
d47cbf1996-12-02Per Hedbor  defines->magic_java="yes";
0943711997-02-25Per Hedbor 
e8790b1998-02-19Per Hedbor  return replace(res +
b9de771999-05-19Peter Bortas  magic_image(url||"", size->xsize, size->ysize, "i"+(defines->mi++), query_internal_location()+num+"/"+gif, query_internal_location()+num2+"/"+gif,
e8790b1998-02-19Per Hedbor  (arg->alt?arg->alt:replace(gt, "\"","'")), (magic=="magic"?0:magic),
dd8da81998-09-21Johan Schön  id,input?na||"submit":0,ea,lp),
e8790b1998-02-19Per Hedbor  "</script>\n<script>","");
d47cbf1996-12-02Per Hedbor  }
ca0f081997-02-22Per Hedbor  if(input)
0943711997-02-25Per Hedbor  return (pre+"<input type=image name=\""+na+"\" border=0 alt=\""+
eab4221997-09-19Johan Schön  (arg->alt?arg->alt:replace(gt,"\"","'"))+
b9de771999-05-19Peter Bortas  "\" src="+query_internal_location()+num+gif
0943711997-02-25Per Hedbor  +" align="+(al || defalign)+ea+
b9de771999-05-19Peter Bortas  (size?(" width="+size->xsize+" height="+size->ysize):"")+">"+ rest+post);
974b2a1997-10-02Peter Bortas  return (pre+(lp?lp:"")
41d0f91998-02-20Per Hedbor  + "<img border=0 alt=\""
219eec1998-02-02Jens Utbult  + (arg->alt?arg->alt:replace(gt,"\"","'"))
974b2a1997-10-02Peter Bortas  + "\" src=\""
b9de771999-05-19Peter Bortas  + query_internal_location()+num+gif+"\" "+ea
974b2a1997-10-02Peter Bortas  + " align="+(al || defalign)
b9de771999-05-19Peter Bortas  + (size?(" width="+size->xsize+" height="+size->ysize):"")+">"+ rest+(lp?"</a>":"")+post);
d47cbf1996-12-02Per Hedbor }
bfc7071997-01-13Per Hedbor inline string ns_color(array (int) col) { if(!arrayp(col)||sizeof(col)!=3) return "#000000"; return sprintf("#%02x%02x%02x", col[0],col[1],col[2]); }
fc57521998-03-06Per Hedbor string|array (string) tag_body(string t, mapping args, object id, object file, mapping defines)
d47cbf1996-12-02Per Hedbor {
bfc7071997-01-13Per Hedbor  int cols,changed;
fc57521998-03-06Per Hedbor  if(args->help) return "This tag is parsed by &lt;gtext&gt; to get the document colors.";
bfc7071997-01-13Per Hedbor  if(args->bgcolor||args->text||args->link||args->alink ||args->background||args->vlink) cols=1;
c97c421998-08-20Per Hedbor #define FIX(Y,Z,X) do{if(!args->Y || args->Y==""){if(cols){defines->X=Z;args->Y=Z;changed=1;}}else{defines->X=args->Y;if(QUERY(colormode)&&args->Y[0]!='#'){args->Y=ns_color(parse_color(args->Y));changed=1;}}}while(0)
bfc7071997-01-13Per Hedbor 
2ce3701998-03-29Henrik Grubbström (Grubba)  if(!search((id->client||({}))*"","Mosaic"))
0ee0851997-02-08Per Hedbor  { FIX(bgcolor,"#bfbfbf",bg); FIX(text, "#000000",fg); FIX(link, "#0000b0",link); FIX(alink, "#3f0f7b",alink); FIX(vlink, "#ff0000",vlink); } else { FIX(bgcolor,"#c0c0c0",bg); FIX(text, "#000000",fg); FIX(link, "#0000ee",link); FIX(alink, "#ff0000",alink); FIX(vlink, "#551a8b",vlink); }
c97c421998-08-20Per Hedbor  if(changed && QUERY(colormode)) return ({make_tag("body", args) });
d47cbf1996-12-02Per Hedbor }
196dac1997-02-22Per Hedbor 
fc57521998-03-06Per Hedbor string|array(string) tag_fix_color(string tagname, mapping args, object id, object file, mapping defines)
bfc7071997-01-13Per Hedbor { int changed;
196dac1997-02-22Per Hedbor 
fc57521998-03-06Per Hedbor  if(args->help) return "This tag is parsed by &lt;gtext&gt; to get the document colors.";
196dac1997-02-22Per Hedbor  if(!id->misc->colors)
5f0d911997-02-27Per Hedbor  id->misc->colors = ({ ({ defines->fg, defines->bg, tagname }) });
196dac1997-02-22Per Hedbor  else
5f0d911997-02-27Per Hedbor  id->misc->colors += ({ ({ defines->fg, defines->bg, tagname }) });
f7d9811997-09-12Per Hedbor #undef FIX
c97c421998-08-20Per Hedbor #define FIX(X,Y) if(args->X && args->X!=""){defines->Y=args->X;if(QUERY(colormode) && args->X[0]!='#'){args->X=ns_color(parse_color(args->X));changed = 1;}}
bfc7071997-01-13Per Hedbor  FIX(bgcolor,bg); FIX(text,fg); FIX(color,fg);
c97c421998-08-20Per Hedbor #undef FIX
22846b1998-05-15Per Hedbor 
c97c421998-08-20Per Hedbor  if(changed && QUERY(colormode)) return ({ make_tag(tagname, args) });
bfc7071997-01-13Per Hedbor  return 0; }
d47cbf1996-12-02Per Hedbor 
fc57521998-03-06Per Hedbor string|void pop_color(string tagname,mapping args,object id,object file,
196dac1997-02-22Per Hedbor  mapping defines) {
fc57521998-03-06Per Hedbor  if(args->help) return "This end-tag is parsed by &lt;gtext&gt; to get the document colors.";
c97c421998-08-20Per Hedbor  array c = id->misc->colors;
0a76aa1998-03-27David Hedbor  if(!c ||!sizeof(c)) return;
df8d711998-02-27Per Hedbor  int i; tagname = tagname[1..]; for(i=0;i<sizeof(c);i++) if(c[-i-1][2]==tagname)
5f0d911997-02-27Per Hedbor  {
df8d711998-02-27Per Hedbor  defines->fg = c[-i-1][0]; defines->bg = c[-i-1][1];
5f0d911997-02-27Per Hedbor  break; }
0a76aa1998-03-27David Hedbor  c = c[..sizeof(c)-i-2];
5f0d911997-02-27Per Hedbor  id->misc->colors = c;
196dac1997-02-22Per Hedbor }
bfc7071997-01-13Per Hedbor mapping query_tag_callers()
d47cbf1996-12-02Per Hedbor {
b9de771999-05-19Peter Bortas  mapping tags = ([ ]);
39af1a1998-08-26Per Hedbor  if(query("colorparse")) foreach(query("colorparsing"), string t)
c97c421998-08-20Per Hedbor  {
39af1a1998-08-26Per Hedbor  switch(t) { case "body": tags[t] = tag_body; break; default: tags[t] = tag_fix_color; tags["/"+t]=pop_color; }
c97c421998-08-20Per Hedbor  } return tags;
d47cbf1996-12-02Per Hedbor } mapping query_container_callers() { return ([ "anfang":tag_graphicstext,
b9de771999-05-19Peter Bortas  "gtext-id":tag_gtext_id, "gh":tag_graphicstext,
bfc7071997-01-13Per Hedbor  "gh1":tag_graphicstext, "gh2":tag_graphicstext, "gh3":tag_graphicstext, "gh4":tag_graphicstext, "gh5":tag_graphicstext, "gh6":tag_graphicstext,
d47cbf1996-12-02Per Hedbor  "gtext":tag_graphicstext, ]); }