Roxen.git / server / modules / graphics / graphic_text.pike

version» Context lines:

Roxen.git/server/modules/graphics/graphic_text.pike:1: - constant cvs_version="$Id: graphic_text.pike,v 1.195 1999/12/09 09:58:24 nilsson Exp $"; + constant cvs_version="$Id: graphic_text.pike,v 1.196 1999/12/11 20:39:34 nilsson Exp $";   constant thread_safe=1;      #include <config.h>   #include <module.h>   #include <stat.h>   inherit "module";   inherit "roxenlib";         // ------------------- Module registration ---------------------
Roxen.git/server/modules/graphics/graphic_text.pike:47:    "&lt;gh1&gt;&lt;/gh&gt;, which would otherwise parse the"    " whole document. This can be overrided with maxlen=... in the "    "tag.");       defvar("ext", 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");   }    - TAGDOCUMENTATION + TAGDOCUMENTATION;   #ifdef manual   constant gtextargs="";   constant tagdoc=(["gtext":"<desc cont></desc>"+gtextargs,    "gtext-id":"<desc tag></desc>"+gtextargs,    "anfang":"<desc cont></desc>"+gtextargs,    "gtext-url":"<desc cont></desc>"+gtextargs,    "gh":"<desc cont></desc>"+gtextargs,    "gh1":"<desc cont></desc>"+gtextargs,    "gh2":"<desc cont></desc>"+gtextargs,    "gh3":"<desc cont></desc>"+gtextargs,    "gh4":"<desc cont></desc>"+gtextargs,    "gh5":"<desc cont></desc>"+gtextargs,    "gh6":"<desc cont></desc>"+gtextargs]);   #endif         // ------------------- The actual graphics routines ----------------------    - #define MAX(a,b) ((a)<(b)?(b):(a)) - #define MIN(a,b) ((a)<(b)?(a):(b)) -  +    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 = allocate(size, allocate)(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); +  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) + Image.Image 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, + Image.Image outline(Image.Image on, Image.Image 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;   }      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 });    - object bevel(object in, int width, int|void invert) + Image.Image bevel(Image.Image 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); +  Image.Image corner = Image.Image(width+1,width+1); +  Image.Image corner2 = Image.Image(width+1,width+1); +  Image.Image 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);
Roxen.git/server/modules/graphics/graphic_text.pike:153:    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, RequestID id) + Image.Image make_text_image(mapping args, Image.Font font, string text, RequestID id)   {    if( args->encoding )    text = roxen.decode_charset(args->encoding,text); -  object text_alpha=font->write(@(text/"\n")); +  Image.Image text_alpha=font->write(@(text/"\n"));    int xoffset=0, yoffset=0;       if(!text_alpha->xsize() || !text_alpha->ysize())    text_alpha = Image.Image(10,10, 0,0,0);       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.
Roxen.git/server/modules/graphics/graphic_text.pike:217:    {    xsize+=6;    ysize+=6;    xoffset+=3;    yoffset+=3;    }       if(args->move)    {    int dx,dy; -  sscanf(args->move, "%d,%d", dx, dy); +  if(sscanf(args->move, "%d,%d", dx, dy)==2) +  m_delete(args,"move"); +  else {    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)
Roxen.git/server/modules/graphics/graphic_text.pike:247:    {    xoffset += (int)args->border;    yoffset += (int)args->border;    xsize += ((int)args->border)*2;    ysize += ((int)args->border)*2;    }       array (int) bgcolor = parse_color(args->bgcolor);    array (int) fgcolor = parse_color(args->fgcolor);    -  object background,foreground; +  Image.Image background,foreground;       if(args->texture)    { -  object t = roxen.load_image(args->texture,id); +  Image.Image t = roxen.load_image(args->texture,id);    if( t )    {    foreground = t;    if(args->tile)    { -  object b2 = Image.Image(xsize,ysize); +  Image.Image b2 = Image.Image(xsize,ysize);    for(int x=0; x<xsize; x+=foreground->xsize())    for(int y=0; y<ysize; y+=foreground->ysize())    b2->paste(foreground, x, y);    foreground = b2;    } else if(args->mirrortile) { -  object b2 = Image.Image(xsize,ysize); -  object b3 = Image.Image(foreground->xsize()*2,foreground->ysize()*2); +  Image.Image b2 = Image.Image(xsize,ysize); +  Image.Image 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)
Roxen.git/server/modules/graphics/graphic_text.pike:293:    werror("Failed to load image for "+args->texture+"\n");    }    int background_is_color;    if(args->background &&    ((background = roxen.load_image(args->background, id)) ||    (sizeof(args->background)>1 &&    (background=Image.Image(xsize,ysize,    @(parse_color(args->background[1..]))))    && (background_is_color=1))))    { -  object alpha; +  Image.Image alpha;    if(args->alpha && (alpha = roxen.load_image(args->alpha,id)) && background_is_color)    { -  xsize=MAX(xsize,alpha->xsize()); -  ysize=MAX(ysize,alpha->ysize()); +  xsize=max(xsize,alpha->xsize()); +  ysize=max(ysize,alpha->ysize());    if((float)args->scale)    alpha=alpha->scale(1/(float)args->scale);    background=Image.Image(xsize,ysize, @(parse_color(args->background[1..])));    }       if((float)args->scale >= 0.1 && !alpha)    background = background->scale(1.0/(float)args->scale);       if(args->tile)    { -  object b2 = Image.Image(xsize,ysize); +  Image.Image 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); +  Image.Image b2 = Image.Image(xsize,ysize); +  Image.Image 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;    } -  xsize = MAX(xsize,background->xsize()); -  ysize = MAX(ysize,background->ysize()); +  xsize = max(xsize,background->xsize()); +  ysize = max(ysize,background->ysize());       if(alpha)    background->paste_alpha_color(alpha->invert(),@bgcolor);       switch(lower_case(args->talign||"left")) {    case "center":    xoffset = (xsize/2 - txsize/2);    yoffset = (ysize/2 - tysize/2);    break;    case "right":
Roxen.git/server/modules/graphics/graphic_text.pike:430:    if(args->ghost)    { // Francesco..    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(); +  Image.Image 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;    }    }       if(args->shadow)    {    int sd = ((int)args->shadow+10)*2;    int sdist = ((int)(args->shadow/",")[-1])+2; -  object ta = text_alpha->copy(); +  Image.Image 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);    }       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); +  Image.Image 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); +  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,
Roxen.git/server/modules/graphics/graphic_text.pike:546:   }      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)      mixed draw_callback(mapping args, string text, RequestID id)   { -  object|array data; +  array data; +  Image.Font font;    Image.Image img;    int elapsed;       if( objectp( text ) )    {    if( !args->text )    error("Failed miserably to find a text to draw. That's not"    " good.\n");    id = (object)text;    text = args->text;
Roxen.git/server/modules/graphics/graphic_text.pike:599:    }    res+="\n";    }    text=replace(res[..strlen(res)-2], ({"!","?",": "}),({ nbsp+"!",nbsp+"?",nbsp+": "}));    text=replace(replace(replace(text,({". ",". "+nbsp}),    ({"\000","\001"})),".","."+nbsp+nbsp),    ({"\000","\001"}),({". ","."+nbsp}));    }       if( args->afont ) -  data = resolve_font(args->afont+" "+(args->font_size||32)); +  font = resolve_font(args->afont+" "+(args->font_size||32));    else    {    if(!args->nfont) args->nfont = args->font;    int bold=0, italic=0;    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", +  font = 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);    }    -  if (!data) +  if (!font)    error("gtext: No font!\n");       // Fonts and such are now initialized. -  img = make_text_image(args,data,text,id); +  img = make_text_image(args, font, text, id);       // Now we have the image in 'img', or nothing.       if( !args->scroll && !args->fadein )    {    if(!args->notrans)    {    array (int) bgcolor = parse_color(args->bgcolor); -  object alpha; +  Image.Image alpha;    alpha = img->distancesq( @bgcolor );    alpha->gamma( 8 );    return ([ "img":img, "alpha":alpha ]);    }    return img;    }       if(args->fadein)    {    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)    { -  object foo=Image.Image(img->xsize(),img->ysize(),@parse_color(args->bgcolor)); +  Image.Image foo=Image.Image(img->xsize(),img->ysize(),@parse_color(args->bgcolor));    res += foo->gif_add(0,0,initialdelay);    }    for(int i = 0; i<(steps-1); i++)    { -  object foo=img->clone(); +  Image.Image foo=img->clone();    foo = foo->apply_matrix(make_matrix(( (int)((steps-i)*amount))));    res += foo->gif_add(0,0,delay);    } -  res+= img->gif_add(0,0,delay); +  res += img->gif_add(0,0,delay);    res += img->gif_end();    data = ({ res, ({ img->xsize(), img->ysize() }) });    }    else    {    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);
Roxen.git/server/modules/graphics/graphic_text.pike:684:    "data":data[0],    "meta":    ([    "xsize":data[1][0],    "ysize":data[1][1],    "type":(args->format?id->conf->type_from_filename("x."+args->format):"image/gif"),    ])    ]);   }    - mapping find_internal(string f, object rid) + mapping find_internal(string f, RequestID id)   {    if( strlen(f)>4 && query("ext") && f[-4]=='.') // Remove .ext    f = f[..strlen(f)-5];    if( strlen(f) && f[0]=='$' )    {    array id_text = f/"/";    if( sizeof(id_text)==2 )    { // It's a gtext-id    string second_key = roxen->argcache->store( (["":id_text[1]]) ); -  return image_cache->http_file_answer( id_text[0][1..] +"$"+ second_key, rid ); +  return image_cache->http_file_answer( id_text[0][1..] +"$"+ second_key, id );    }    } -  return image_cache->http_file_answer( f, rid ); +  return image_cache->http_file_answer( f, id );   }         // -------------- helpfunctions to gtext tags and containers -----------------      constant filearg=({"background","texture","alpha","magic-texture","magic-background","magic-alpha"});   constant textarg=({"afont",    "alpha",    "bevel",    "bgcolor",
Roxen.git/server/modules/graphics/graphic_text.pike:817:       c = c[..(((int)m->maxlen||QUERY(deflen))-1)];    m_delete(m, "maxlen");       return c;   }         // ----------------- gtext tags and containers -------------------    - string tag_gtext_url(string t, mapping arg, string c, RequestID id) { + string container_gtext_url(string t, mapping arg, string c, RequestID id) {    c=fix_text(c,arg,id);    mapping p=mk_gtext_arg(arg,id);    if(arg->href && !p->fgcolor) p->fgcolor=id->misc->defines->link||"#0000ff";    string ext="";    if(query("ext")) ext="."+(p->format || "gif");    if(!arg->short)    return query_internal_location()+image_cache->store( ({p,c}), id )+ext; -  else +     return "+"+image_cache->store( ({p,c}), id )+ext;   }      string tag_gtext_id(string t, mapping arg, RequestID id) {    mapping p=mk_gtext_arg(arg,id);    if(arg->href && !p->fgcolor) p->fgcolor=id->misc->defines->link||"#0000ff";    if(!arg->short)    return query_internal_location()+"$"+image_cache->store(p, id)+"/"; -  else -  return "+"+image_cache->store(p, id )+"/"; +  return "+"+image_cache->store(p, id )+"/foo";   }    - string tag_graphicstext(string t, mapping arg, string c, RequestID id) + string container_gtext(string t, mapping arg, string c, RequestID id)   {    mapping defines=id->misc->defines;    if((c-" ")=="")    return "";       c=fix_text(c,arg,id);    mapping p=mk_gtext_arg(arg,id);       string ext="";    if(query("ext")) ext="."+(p->format || "gif");
Roxen.git/server/modules/graphics/graphic_text.pike:920:       foreach(glob("magic-*", indices(arg)), string q)    {    p[q[6..]]=arg[q];    m_delete(arg, q);    }       string num2 = image_cache->store( ({ p, c }),id );    size = image_cache->metadata( num2, id );    if(size) { -  arg->width=MAX(arg->xsize,size->xsize); -  arg->height=MAX(arg->ysize,size->ysize); +  arg->width=max(arg->xsize,size->xsize); +  arg->height=max(arg->ysize,size->ysize);    }       if(!id->supports->images) return sprintf(lp,arg->alt);       string sn="i"+defines->mi++;    if(!id->supports->netscape_javascript) {    return (!input)?    ("<a "+ea+"href=\""+url+"\">"+make_tag("img",arg+(["name":sn]))+"</a>"):    make_tag("input",arg+(["type":"image"]));    }
Roxen.git/server/modules/graphics/graphic_text.pike:961:    "onMouseout=\"top.window.status='';document.images['"+sn+"'].src = "+sn+"l.src;\">"    +make_tag("img",arg)+"</a>";    }       if(input)    return make_tag("input",arg+(["type":"image"]));       return sprintf(lp,make_tag("img",arg));   }    - array(string) tag_gh(string t, mapping m, string c, RequestID id) { + array(string) container_gh(string t, mapping m, string c, RequestID id) {    int i;    if(sscanf(t, "%s%d", t, i)==2 && i>1)    m->scale = (string)(1.0 / ((float)i*0.6));    if(!m->valign) m->valign="top"; -  return ({ "<p>"+tag_graphicstext("",m,c,id)+"<br>" }); +  return ({ "<p>"+container_gtext("",m,c,id)+"<br>" });   }    - array(string) tag_anfang(string t, mapping m, string c, RequestID id) { + array(string) container_anfang(string t, mapping m, string c, RequestID id) {    if(!m->align) m->align="left"; -  return ({ "<br clear=\"left\">"+tag_graphicstext("",m,c[0..0],id)+c[1..] }); +  return ({ "<br clear=\"left\">"+container_gtext("",m,c[0..0],id)+c[1..] });   }         // ------------ Wiretap code to find HTML-colours ---------------------      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]);   }    - int|array (string) tag_body(string t, mapping args, RequestID id, object file, + int|array (string) tag_body(string t, mapping args, RequestID id, Stdio.File file,    mapping defines)   {    int changed=0;    int cols=(args->bgcolor||args->text||args->link||args->alink||args->vlink);      #define FIX(Y,Z,X) do{if(!args->Y || args->Y==""){defines->X=Z;if(cols){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)       if(!search((id->client||({}))*"","Mosaic"))    {    FIX(bgcolor,"#bfbfbf",bgcolor);
Roxen.git/server/modules/graphics/graphic_text.pike:1012:    FIX(link, "#0000ee",link);    FIX(alink, "#ff0000",alink);    FIX(vlink, "#551a8b",vlink);    }    if(changed && QUERY(colormode))    return ({make_tag("body", args) });    return 0;   }      string|array(string) tag_fix_color(string tagname, mapping args, RequestID id, -  object file, mapping defines) +  Stdio.File file, mapping defines)   {    int changed;       if(!id->misc->colors)    id->misc->colors = ({ ({ defines->fgcolor, defines->bgcolor, tagname }) });    else    id->misc->colors += ({ ({ defines->fgcolor, defines->bgcolor, tagname }) });   #undef FIX   #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;}}       FIX(bgcolor,bgcolor);    FIX(color,fgcolor);    FIX(text,fgcolor);   #undef FIX       if(changed && QUERY(colormode))    return ({ make_tag(tagname, args) });    return 0;   }    - string|void pop_color(string tagname,mapping args,RequestID id,object file, + string|void tag_pop_color(string tagname, mapping args, RequestID id, Stdio.File file,    mapping defines)   {    array c = id->misc->colors;    if(!c ||!sizeof(c))    return;       int i;    tagname = tagname[1..];       for(i=0;i<sizeof(c);i++)
Roxen.git/server/modules/graphics/graphic_text.pike:1070:    if(query("colorparse"))    foreach(query("colorparsing"), string t)    {    switch(t)    {    case "body":    tags[t] = tag_body;    break;    default:    tags[t] = tag_fix_color; -  tags["/"+t]=pop_color; +  tags["/"+t]=tag_pop_color;    }    }    return tags;   }      mapping query_container_callers()   { -  return ([ "anfang":tag_anfang, -  "gtext-url":tag_gtext_url, "gh":tag_gh, -  "gh1":tag_gh, "gh2":tag_gh, -  "gh3":tag_gh, "gh4":tag_gh, -  "gh5":tag_gh, "gh6":tag_gh, -  "gtext":tag_graphicstext ]); +  return ([ "anfang":container_anfang, +  "gtext-url":container_gtext_url, "gh":container_gh, +  "gh1":container_gh, "gh2":container_gh, +  "gh3":container_gh, "gh4":container_gh, +  "gh5":container_gh, "gh6":container_gh, +  "gtext":container_gtext ]);   }