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

version» Context lines:

Roxen.git/server/modules/graphics/graphic_text.pike:1: - string cvs_version="$Id: graphic_text.pike,v 1.21 1996/12/10 13:19:40 neotron Exp $"; + string cvs_version="$Id: graphic_text.pike,v 1.22 1997/01/13 06:54:50 per Exp $";   #include <module.h>   inherit "module";   inherit "roxenlib";         array register_module()   {    return ({ MODULE_LOCATION | MODULE_PARSER,    "Graphics text",    "Makes a few new tags, which render text to gifs "    "using the image module in pike. \n<p>"    "<b>&lt;gh1&gt;</b> to <b>&lt;gh6&gt;:</b> Headers<br>\n"    "<b>&lt;gh&gt;:</b> Header<br>\n"    "<b>&lt;gtext&gt;:</b> Graphical text<br>\n"    "<b>&lt;anfang&gt;:</b> Make the first character to a graphical one. Not all that usefull, really.<br>\n"    "<br>\n"    "<b>Common arguments:</b>\n <pre>" -  " bg=#rrggbb Use this background, default taken from the\n" +  " bg=color Use this background, default taken from the\n"    " &lt;body&gt; tag, if any\n" -  " fg=#rrggbb Use this foreground, default taken from the\n" +  " fg=color Use this foreground, default taken from the\n"    " &lt;body&gt; tag, if any\n"    " font=fnt Use this font. The fonts can be found in the\n"    " directory specified in the configuration\n"    " interface.\n"    " If no font is specified, the one from the\n"    " define 'font' is used, or if there is no\n"    " define, the default font will be used.\n"    " scale=float Scale to this font, mostly useful in the &lt;gtext&gt;\n"    " tag, will not work at all in the &lt;gh[number]&gt;\n"    " tags.\n"    " 2 3 4 5 6 Short for scale=1.0/([number]*0.6)\n"    " notrans Do _not_ make the background color transparent\n"    " split Make each word into a separate gif image\n"    " href=url Link the image to the specified URL\n"    " The 'link' color of the document will be\n"    " used as the default foreground of the text\n"    " quant=cols Use this number of colors\n"    " magic[=message] Modifier to href, more flashy links\n"    " Does <b>not</b> work with 'split'\n" -  +  " fuzz[=color] Apply the 'glow' effect to the result\n"    " fs Use floyd-steinberg dithering\n" -  " border=int,#col Draw an border (width is the first argument\n" +  " border=int,col. Draw an border (width is the first argument\n"    " in the specified color\n"    " spacing=int Add this amount of spacing around the text\n"    " xspacing=int like spacing, but only horizontal\n"    " yspacing=int like spacing, but only vertical\n"    " size=int,int Use this (absolute) size\n"    " xsize=int Use this (absolute) size\n"    " ysize=int Use this (absolute) size\n"    " bevel=int Draw a bevel box (width is the argument)\n"    " pressed Invert the \"direction\" of the bevel box\n"    " talign=dir Justify the text to the left, right, or center\n" -  " textbox=al,#col Use 'al' as opaque value to draw a box below\n" +  " textbox=al,col. Use 'al' as opaque value to draw a box below\n"    " the text with the specified color.\n"    " xpad=X% Increase padding between characters with X%\n"    " xpad=Y% Increase padding between lines with Y%\n"    " shadow=int,dist Draw a drop-shadow (variable distance/intensity)\n" -  " fuzz=#col The 'shine' effect used in the 'magic'\n" -  " highlightning\n" +  " glow=color Draw a 'glow' outline around the text.\n"    " opaque=0-100% Draw with more or less opaque text (100%\n"    " is default)\n"    " rotate=ang(deg.)Rotate the finished image\n"    " background=file Use the specifed file as a background\n"    " texture=file Use the specified file as text texture\n"    " turbulence=args args is: frequency,color;freq,col;freq,col\n"    " Apply a turbulence filter, and use this as the\n"    " background.\n" -  +  " maxlen=arg The maximum length of the rendered text will be\n" +  " the specified argument. The default is 300, this\n" +  " is used to safeguard against mistakes like\n" +  "&lt;gh1&gt;&lt;/gh&gt;, which would otherwise parse the whole\n" +  "document.\n"    "\n"    "<b>Arguments passed on the the &lt;a&gt; tag (if href is specified):</b>\n "    " target=...\n"    " onClick=...\n"    "</pre>\n",    0,    1,    });   }   
Roxen.git/server/modules/graphics/graphic_text.pike:83:    if(!fnts)    {    report_error("Failed to find any fonts in 'fonts/32/'. No default font.\n");    return ({});    }    return fnts;   }      void create()   { +  +  defvar("deflen", 300, "Default maximum text-length", TYPE_INT, +  "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."); +     defvar("location", "/gtext/", "Mountpoint", TYPE_LOCATION,    "The URL-prefix for the anfang characters.");       defvar("cols", 16, "Default number of colors per image", TYPE_INT_LIST,    "The default number of colors to use. 16 seems to be enough. "    "The size of the image depends on the number of colors",    ({ 1,2,3,4,5,6,7,8,10,16,32,64,128,256 }));       defvar("default_size", 32, "Default font size", TYPE_INT_LIST,    "The default size for the font. This is used for the 'base' size, "
Roxen.git/server/modules/graphics/graphic_text.pike:171:    if(!img->frompnm(data) && !img->fromgif(data)) return 0;      // last_image_name=f;   // last_image=img;   //call_out(lambda(){last_image=last_image_name=0;}, 10);    return img/*->copy()*/;   }      object (Image) blur(object (Image) 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()+10))); +  img = img->apply_matrix( make_matrix((int)sqrt(img->ysize()+20)));    return img;   }    -  + object (Image) outline(object (Image) on, object (Image) with, +  array (int) color, int radie, int x, int y) + { +  object foo = Image(with->xsize(), with->ysize(), @color); +  +  int steps=10; +  for(int j=0; j<=steps; j++) +  on->paste_mask(foo, with,(int)(0.5+x-(sin((float)j/steps*PI*2)*radie)), +  (int)(0.5+y-(cos((float)j/steps*PI*2)*radie))); +  foo=0; +  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 (Image) bevel(object (Image) in, int width, int|void invert)   {    int h=in->ysize();    int w=in->xsize();
Roxen.git/server/modules/graphics/graphic_text.pike:231:       return in;   }         object (Image) make_text_image(mapping args, object font, string text)   {    object (Image) text_alpha=font->write(@(text/"\n"));    int xoffset=0, yoffset=0;    +  if(!text_alpha->xsize() || !text_alpha->ysize()) +  text_alpha = 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)    {
Roxen.git/server/modules/graphics/graphic_text.pike:309:    xoffset = (xsize/2 - txsize/2);    break;    case "right":    xoffset = (xsize - txsize);    break;    case "left":    }    } else    background = 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;    background = background->copy(0,0,xs,ys);    }
Roxen.git/server/modules/graphics/graphic_text.pike:348:    {    int alpha,border;    string bg;    sscanf(args->textbox, "%d,%s", alpha, bg);    sscanf(bg,"%s,%d", bg,border);    background->paste_alpha(Image(txsize+border*2,tysize+border*2,    @parse_color(bg)),    255-(alpha*255/100),xoffset-border,yoffset-border);    }    +     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);    background->paste_mask(Image(txsize,tysize),ta,xoffset+sdist, yoffset+sdist);    }    -  +  if(args->glow) +  { +  int amnt = (int)(args->glow/",")[-1]+2; +  array (int) blurc = parse_color((args->glow/",")[0]); +  background->paste_mask(Image(txsize+amnt*2,tysize*2, @blurc), +  blur(text_alpha, amnt), +  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(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);       background->paste_mask(foreground, text_alpha, xoffset, yoffset);       foreground = text_alpha = 0;          if(args->scale)    if((float)args->scale <= 2.0)    background = background->scale((float)args->scale);       if(args->rotate)    {    string c; -  if(sscanf(args->rotate, "%*d,%s", 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;   }
Roxen.git/server/modules/graphics/graphic_text.pike:430:       // Fonts and such are now initialized.       img = make_text_image(args,data,text);       // Now we have the image in 'img', or nothing.       if(!img) return 0;       // place in cache. -  int q = (int)args->quant || (args->background?256:16); +  int q = (int)args->quant || (args->background||args->texture?256:QUERY(cols)); +  if(!args->fs)    img = img->map_closest(img->select_colors(q-1)+({parse_color(args->bg)}));    if(args->fs)    data=({ img->togif_fs(@(args->notrans?({}):parse_color(args->bg))),    ({img->xsize(),img->ysize()})});    else    data=({ img->togif(@(args->notrans?({}):parse_color(args->bg))),    ({img->xsize(),img->ysize()})});    img=0;       cache_set("gtext:"+(_args-_start), text, data);
Roxen.git/server/modules/graphics/graphic_text.pike:555:    " "+sn+".src = \""+image_1+"\";\n"    " "+sn+"2 = new Image("+xs+", "+ys+");\n"    " "+sn+"2.src = \""+image_2+"\";\n"    "}\n"    "// -->\n"    "</script>\n"+    ("<a "+extra_args+"href=\""+url+"\" "+(input?"onClick='document.forms[0].submit();' ":"")    +"onMouseover=\"img_act('"+sn+"','"    +(mess||url)+"');return true;\"\n"    "\n" -  "onMouseout=\"img_inact('"+sn+"')\"><img _parsed=1 \n" -  " src="+image_1+" name="+sn+" border=0 alt=\""+alt+"\" ></a>\n")); +  "onMouseout=\"img_inact('"+sn+"')\"><img _parsed=1 width="+xs+" " +  "height="+ys+" src="+image_1+" name="+sn+" border=0\nalt=\""+alt+"\" ></a>\n"));   }         string extra_args(mapping in)   {    string s="";    foreach(indices(in), string i)    {    switch(i)    {    case "target": -  case "onClick": +  case "hspace": +  case "vspace": +  case "onclick":    s+=i+"='"+in[i]+"' ";    m_delete(in, i);    break;    }    }    return s;   }      string tag_graphicstext(string t, mapping arg, string contents,    object id, object foo, mapping defines)   { -  if(!strlen(contents)) return ""; // There is no need to make this image. +  contents = parse_rxml(contents, id);// Allow <accessed> inside <gtext>.       string pre, post, defalign, gt, rest, magic;    int i, split;    -  +     // No images here, let's generate an alternative..    if(!id->supports->images || id->prestate->noimages)    {    if(!arg->split) contents=replace(contents,"\n", "\n<br>\n");    if(arg->submit) return "<input type=submit value=\""+contents+"\">";    switch(t)    {    case "gtext":    case "anfang":    if(arg->href)
Roxen.git/server/modules/graphics/graphic_text.pike:610:    rest="<h"+i+">"+contents+"</h"+i+">";    else    rest="<h1>"+contents+"</h1>";    if(arg->href)    return "<a href=\""+arg->href+"\">"+rest+"</a>";    return rest;       }    }    +  contents = contents[..((int)arg->maxlen||QUERY(deflen))]; +  m_delete(arg, "maxlen"); +     if(arg->magic)    {    magic=arg->magic;    m_delete(arg,"magic");    }       int input;    if(arg->submit)    {    input=1;    m_delete(arg,"submit");    }       string lp, url, ea; -  +     ea = extra_args(arg); -  +     if(arg->href)    {    url = arg->href;    lp = "<a href=\""+arg->href+"\" "+ea+">";    if(!arg->fg) arg->fg=defines->link||"#0000ff"; -  m_delete(arg,"href"); +     }       // Modify the 'arg' mapping...    if(defines->fg && !arg->fg) arg->fg=defines->fg;    if(defines->bg && !arg->bg) arg->bg=defines->bg;    if(defines->font && !arg->font) arg->font=defines->font||QUERY(default_font);    if(!arg->font) arg->font = QUERY(default_font);    -  +     if(arg->split)    {    split=1;    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);    }       // Support for <gh1> like things.    if(sscanf(t, "%s%d", t, i)==2)    if(i > 1) arg->scale = 1.0 / ((float)i*0.6);       -  string moreargs=""; -  if(arg->hspace) -  { -  moreargs += "hspace="+arg->hspace+" "; -  m_delete(arg,"hspace"); -  } -  -  if(arg->vspace) -  { -  moreargs += "vspace="+arg->vspace+" "; -  m_delete(arg,"vspace"); -  } -  +     // Now the 'args' mapping is modified enough..    int num = find_or_insert( arg );       gt=contents;    rest="";       if(split)    {    string word;    array res = ({});
Roxen.git/server/modules/graphics/graphic_text.pike:693:       if(lp) res+=({ lp });       gt=replace(gt, "\n", " ");       foreach(gt/" "-({""}), word)    {    array size = write_text(num,word,1,0);    res += ({ "<img _parsed=1 border=0 alt=\""+replace(word,"\"","'")    +"\" src=\'"+pre+quote(word)+"\' width="+ -  size[0]+" height="+size[1]+" "+moreargs+">\n" +  size[0]+" height="+size[1]+" "+ea+">\n"    });    }    if(lp) res+=({ "</a>" });    return res*"";    }       switch(t)    {    case "gh1": case "gh2": case "gh3": case "gh4":    case "gh5": case "gh6": case "gh7":
Roxen.git/server/modules/graphics/graphic_text.pike:719:    gt=contents[0..0]; rest=contents[1..];    pre="<br clear=left>"; post=""; defalign="left";    break;    }       array size = write_text(num,gt,1,0);       if(magic)    {    string res = ""; +  if(!arg->fg) arg->fg=defines->link||"#0000ff";    arg = mkmapping(indices(arg), values(arg)); -  arg->fuzz = arg->fg; +  if(arg->fuzz) +  { +  if(arg->fuzz != "fuzz") +  arg->glow = arg->fuzz; +  else +  arg->glow = arg->fg; +  }    arg->fg = defines->alink||"#ff0000";    if(arg->bevel) arg->pressed=1;    int num2 = find_or_insert(arg);    array size = write_text(num2,gt,1,0);    if(!defines->magic_java) res = magic_javascript_header(id);    defines->magic_java="yes";    return res + magic_image(url||"", size[0], size[1], -  "i"+(num+""+hash(gt,0x7fffffff))+"g", +  "i"+(num+""+hash(gt,0x7fffffff)+hash(url||"",0x7fffffff))+"g",    query_location()+num+"/"+quote(gt),    query_location()+num2+"/"+quote(gt),    replace(gt, "\"","'"),(magic=="magic"?0:magic),    id,input?(arg->name||"submit"):0,ea);    }    if(input && id->supports->images)    return (pre+"<input type=image name=\""+arg->name+"\" border=0 alt=\""+    replace(gt,"\"","'")+"\" src="+query_location()+num+"/"+quote(gt) -  +" align="+(arg->align?arg->align:defalign)+ +  +" align="+(arg->align?arg->align:defalign)+ea+    " width="+size[0]+" height="+size[1]+">"+rest+post);    return (pre+(lp?lp:"")+    "<img _parsed=1 border=0 alt=\""+replace(gt,"\"","'")+"\" src="+ -  query_location()+num+"/"+quote(gt) +  query_location()+num+"/"+quote(gt)+" "+ea    +" align="+(arg->align?arg->align:defalign)+    " width="+size[0]+" height="+size[1]+">"+rest+(lp?"</a>":"")+post);   }    -  + 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]); + } +  +  + string make_args(mapping in) + { +  array a=indices(in), b=values(in); +  for(int i=0; i<sizeof(a); i++) +  if(lower_case(b[i])!=a[i]) +  if(search(b,"\"")==-1) +  a[i]+="=\""+b[i]+"\""; +  else +  a[i]+="='"+b[i]+"'"; +  return a*" "; + } +    string tag_body(string t, mapping args, object id, object file,    mapping defines)   { -  int bg, text, link, alink, vlink, background; - //if(args->clink) { defines->clink = args->clink; -  if(args->bgcolor) { defines->bg = args->bgcolor; bg=1; } -  if(args->text) { defines->fg = args->text; text=1; } -  if(args->link) { defines->link = args->link; link=1; } -  if(args->background){ background=1; } -  if(args->alink) { defines->alink = args->alink; alink=1;} -  if(args->vlink) { defines->vlink = args->vlink; vlink=1;} -  if(bg+text+link+alink+vlink+background+bg&& -  (bg+text+link+alink+vlink+background+bg)<5) -  { -  if(!bg) args->bgcolor=args->text || "black"; -  if(!text) args->text=args->bgcolor || "white"; -  if(!link) args->link=args->bgcolor || "yellow"; -  if(!vlink)args->vlink=args->bgcolor || "pink"; -  if(!alink)args->alink=args->bgcolor || "red"; -  return ("<body "+(background?"background="+args->background+" ":"")+ -  "bgcolor="+args->bgcolor+" text="+args->text+" link="+ -  args->link+" vlink="+args->vlink+" alink="+args->alink+">"); +  int cols,changed; +  if(args->bgcolor||args->text||args->link||args->alink +  ||args->background||args->vlink) +  cols=1; +  + #define FIX(Y,Z,X) do{if(!args->Y){if(cols){defines->X=Z;args->Y=Z;changed=1;}}else{defines->X=args->Y;if(args->Y[0]!='#'){args->Y=ns_color(parse_color(args->Y));changed=1;}}}while(0) +  +  FIX(bgcolor,"#c0c0c0",bg); +  FIX(text,"#000000",fg); +  FIX(link,"#0000ff",link); +  FIX(alink,"#00ffff",alink); +  FIX(vlink,"#2000ee",vlink); +  if(changed) +  return ("<body "+make_args(args)+">");   } - } +     -  + string tag_fix_color(string tagname, mapping args, object id, object file, +  mapping defines) + { +  int changed; + #define FIX(X,Y) if(args->X){defines->Y=args->X;if(args->X[0]!='#'){args->X=ns_color(parse_color(args->X));changed = 1;}}    -  +  FIX(bgcolor,bg); +  FIX(text,fg); +  FIX(color,fg); +  if(changed)return ("<"+tagname+" "+make_args(args)+">"); +  return 0; + } +    mapping query_tag_callers()   { -  return (["body":tag_body]); +  return ([ +  "body":tag_body, "font":tag_fix_color, +  "table":tag_fix_color, +  "tr":tag_fix_color, "td":tag_fix_color +  ]);   }         mapping query_container_callers()   {    return ([ "anfang":tag_graphicstext,    "gh":tag_graphicstext, -  "gh1":tag_graphicstext, -  "gh2":tag_graphicstext, -  "gh3":tag_graphicstext, -  "gh4":tag_graphicstext, -  "gh5":tag_graphicstext, -  "gh6":tag_graphicstext, +  "gh1":tag_graphicstext, "gh2":tag_graphicstext, +  "gh3":tag_graphicstext, "gh4":tag_graphicstext, +  "gh5":tag_graphicstext, "gh6":tag_graphicstext, +  "gh7":tag_graphicstext, "gh8":tag_graphicstext, +  "gh9":tag_graphicstext, "gh10":tag_graphicstext, +  "gh11":tag_graphicstext,"gh12":tag_graphicstext,    "gtext":tag_graphicstext, ]);   }