30 using System.Drawing.Imaging;
31 using System.Globalization;
37 using OpenMetaverse.Imaging;
38 using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
39 using OpenSim.Region.Framework.Interfaces;
40 using OpenSim.Region.Framework.Scenes;
42 using System.Reflection;
47 namespace OpenSim.
Region.CoreModules.Scripting.VectorRender
49 [Extension(Path =
"/OpenSim/RegionModules", NodeName =
"RegionModule", Id =
"VectorRenderModule")]
57 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
59 private Scene m_scene;
62 private Graphics m_graph;
63 private string m_fontName =
"Arial";
69 #region IDynamicTextureRender Members
99 return Draw(bodyData, extraParams);
109 if (m_textureManager == null)
111 m_log.Warn(
"[VECTORRENDERMODULE]: No texture manager. Can't function");
115 m_textureManager.ReturnData(id, ConvertData(bodyData, extraParams));
121 out
double xSize, out
double ySize)
125 using (Font myFont =
new Font(fontName, fontSize))
127 SizeF stringSize =
new SizeF();
132 stringSize = m_graph.MeasureString(text, myFont);
133 xSize = stringSize.Width;
134 ySize = stringSize.Height;
142 #region ISharedRegionModule Members
146 IConfig cfg = config.Configs[
"VectorRender"];
149 m_fontName = cfg.GetString(
"font_name", m_fontName);
151 m_log.DebugFormat(
"[VECTORRENDERMODULE]: using font \"{0}\" for text rendering.", m_fontName);
155 Bitmap bitmap =
new Bitmap(1024, 1024, PixelFormat.Format32bppArgb);
156 m_graph = Graphics.FromImage(bitmap);
173 if (m_textureManager == null && m_scene == scene)
176 if (m_textureManager != null)
178 m_textureManager.RegisterRender(GetContentType(),
this);
193 get {
return "VectorRenderModule"; }
196 public Type ReplaceableInterface
210 Color bgColor = Color.White;
211 char altDataDelim =
';';
213 char[] paramDelimiter = {
',' };
214 char[] nvpDelimiter = {
':' };
216 extraParams = extraParams.Trim();
217 extraParams = extraParams.ToLower();
219 string[] nvps = extraParams.Split(paramDelimiter);
222 foreach (
string pair
in nvps)
224 string[] nvp = pair.Split(nvpDelimiter);
230 name = nvp[0].Trim();
235 value = nvp[1].Trim();
241 temp = parseIntParam(value);
248 else if (temp > 2048)
259 temp = parseIntParam(value);
266 else if (temp > 2048)
277 temp = parseIntParam(value);
294 else if (value.ToLower() ==
"false") {
301 if (Int32.TryParse(value, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out hex))
303 bgColor = Color.FromArgb(hex);
307 bgColor = Color.FromName(value);
311 altDataDelim = value.ToCharArray()[0];
318 if (name ==
"setalpha")
327 temp = parseIntParam(name);
344 Bitmap bitmap = null;
345 Graphics graph = null;
346 bool reuseable =
false;
358 bitmap =
new Bitmap(width, height, PixelFormat.Format32bppRgb);
360 bitmap =
new Bitmap(width, height, PixelFormat.Format32bppArgb);
362 graph = Graphics.FromImage(bitmap);
368 using (SolidBrush bgFillBrush =
new SolidBrush(bgColor))
370 graph.FillRectangle(bgFillBrush, 0, 0, width, height);
374 for (
int w = 0; w < bitmap.Width; w++)
378 for (
int h = 0; h < bitmap.Height; h++)
380 bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h)));
385 GDIDraw(data, graph, altDataDelim, out reuseable);
388 byte[] imageJ2000 =
new byte[0];
400 imageJ2000 = OpenJPEG.EncodeFromImage(bitmap,
true);
405 "[VECTORRENDERMODULE]: OpenJpeg Encode Failed. Exception {0}{1}",
406 e.Message, e.StackTrace);
410 data, extraParams, imageJ2000,
new Size(width, height), reuseable);
430 private int parseIntParam(
string strInt)
435 parsed = Convert.ToInt32(strInt);
491 private string[] GetLines(
string data,
char dataDelim)
493 char[] lineDelimiter = { dataDelim };
494 return data.Split(lineDelimiter);
497 private void GDIDraw(
string data, Graphics graph,
char dataDelim, out
bool reuseable)
500 Point startPoint =
new Point(0, 0);
501 Point endPoint =
new Point(0, 0);
504 SolidBrush myBrush = null;
508 drawPen =
new Pen(Color.Black, 7);
509 string fontName = m_fontName;
511 myFont =
new Font(fontName, fontSize);
512 myBrush =
new SolidBrush(Color.Black);
514 char[] partsDelimiter = {
','};
516 foreach (
string line
in GetLines(data, dataDelim))
518 string nextLine = line.Trim();
523 if (nextLine.StartsWith(
"MoveTo"))
527 GetParams(partsDelimiter, ref nextLine, 6, ref x, ref y);
528 startPoint.X = (int) x;
529 startPoint.Y = (int) y;
531 else if (nextLine.StartsWith(
"LineTo"))
535 GetParams(partsDelimiter, ref nextLine, 6, ref x, ref y);
536 endPoint.X = (int) x;
537 endPoint.Y = (int) y;
538 graph.DrawLine(drawPen, startPoint, endPoint);
539 startPoint.X = endPoint.X;
540 startPoint.Y = endPoint.Y;
542 else if (nextLine.StartsWith(
"Text"))
544 nextLine = nextLine.Remove(0, 4);
545 nextLine = nextLine.Trim();
546 graph.DrawString(nextLine, myFont, myBrush, startPoint);
548 else if (nextLine.StartsWith(
"Image"))
556 GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y);
557 endPoint.X = (int) x;
558 endPoint.Y = (int) y;
560 using (Image image = ImageHttpRequest(nextLine))
564 graph.DrawImage(image, (float)startPoint.X, (
float)startPoint.Y, x, y);
568 using (Font errorFont =
new Font(m_fontName,6))
570 graph.DrawString(
"URL couldn't be resolved or is", errorFont,
571 myBrush, startPoint);
572 graph.DrawString(
"not an image. Please check URL.", errorFont,
573 myBrush,
new Point(startPoint.X, 12 + startPoint.Y));
576 graph.DrawRectangle(drawPen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y);
580 startPoint.X += endPoint.X;
581 startPoint.Y += endPoint.Y;
583 else if (nextLine.StartsWith(
"Rectangle"))
587 GetParams(partsDelimiter, ref nextLine, 9, ref x, ref y);
588 endPoint.X = (int) x;
589 endPoint.Y = (int) y;
590 graph.DrawRectangle(drawPen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y);
591 startPoint.X += endPoint.X;
592 startPoint.Y += endPoint.Y;
594 else if (nextLine.StartsWith(
"FillRectangle"))
598 GetParams(partsDelimiter, ref nextLine, 13, ref x, ref y);
599 endPoint.X = (int) x;
600 endPoint.Y = (int) y;
601 graph.FillRectangle(myBrush, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y);
602 startPoint.X += endPoint.X;
603 startPoint.Y += endPoint.Y;
605 else if (nextLine.StartsWith(
"FillPolygon"))
607 PointF[] points = null;
608 GetParams(partsDelimiter, ref nextLine, 11, ref points);
609 graph.FillPolygon(myBrush, points);
611 else if (nextLine.StartsWith(
"Polygon"))
613 PointF[] points = null;
614 GetParams(partsDelimiter, ref nextLine, 7, ref points);
615 graph.DrawPolygon(drawPen, points);
617 else if (nextLine.StartsWith(
"Ellipse"))
621 GetParams(partsDelimiter, ref nextLine, 7, ref x, ref y);
624 graph.DrawEllipse(drawPen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y);
625 startPoint.X += endPoint.X;
626 startPoint.Y += endPoint.Y;
628 else if (nextLine.StartsWith(
"FontSize"))
630 nextLine = nextLine.Remove(0, 8);
631 nextLine = nextLine.Trim();
632 fontSize = Convert.ToSingle(nextLine, CultureInfo.InvariantCulture);
635 myFont =
new Font(fontName, fontSize);
637 else if (nextLine.StartsWith(
"FontProp"))
639 nextLine = nextLine.Remove(0, 8);
640 nextLine = nextLine.Trim();
642 string[] fprops = nextLine.Split(partsDelimiter);
643 foreach (
string prop
in fprops)
651 Font newFont =
new Font(myFont, myFont.Style | FontStyle.Bold);
657 if (!(myFont.Italic))
659 Font newFont =
new Font(myFont, myFont.Style | FontStyle.Italic);
665 if (!(myFont.Underline))
667 Font newFont =
new Font(myFont, myFont.Style | FontStyle.Underline);
673 if (!(myFont.Strikeout))
675 Font newFont =
new Font(myFont, myFont.Style | FontStyle.Strikeout);
685 Font newFont =
new Font(myFont, FontStyle.Regular);
693 else if (nextLine.StartsWith(
"FontName"))
695 nextLine = nextLine.Remove(0, 8);
696 fontName = nextLine.Trim();
698 myFont =
new Font(fontName, fontSize);
700 else if (nextLine.StartsWith(
"PenSize"))
702 nextLine = nextLine.Remove(0, 7);
703 nextLine = nextLine.Trim();
704 float size = Convert.ToSingle(nextLine, CultureInfo.InvariantCulture);
705 drawPen.Width = size;
707 else if (nextLine.StartsWith(
"PenCap"))
709 bool start =
true, end =
true;
710 nextLine = nextLine.Remove(0, 6);
711 nextLine = nextLine.Trim();
712 string[] cap = nextLine.Split(partsDelimiter);
713 if (cap[0].ToLower() ==
"start")
715 else if (cap[0].ToLower() ==
"end")
717 else if (cap[0].ToLower() !=
"both")
719 string type = cap[1].ToLower();
726 drawPen.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
729 drawPen.EndCap = System.Drawing.Drawing2D.LineCap.RoundAnchor;
732 drawPen.EndCap = System.Drawing.Drawing2D.LineCap.DiamondAnchor;
735 drawPen.EndCap = System.Drawing.Drawing2D.LineCap.Flat;
744 drawPen.StartCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
747 drawPen.StartCap = System.Drawing.Drawing2D.LineCap.RoundAnchor;
750 drawPen.StartCap = System.Drawing.Drawing2D.LineCap.DiamondAnchor;
753 drawPen.StartCap = System.Drawing.Drawing2D.LineCap.Flat;
758 else if (nextLine.StartsWith(
"PenColour") || nextLine.StartsWith(
"PenColor"))
760 nextLine = nextLine.Remove(0, 9);
761 nextLine = nextLine.Trim();
765 if (Int32.TryParse(nextLine, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out hex))
767 newColor = Color.FromArgb(hex);
772 newColor = Color.FromName(nextLine);
775 myBrush.Color = newColor;
776 drawPen.Color = newColor;
793 private static void GetParams(
char[] partsDelimiter, ref
string line,
int startLength, ref
float x, ref
float y)
795 line = line.Remove(0, startLength);
796 string[] parts = line.Split(partsDelimiter);
797 if (parts.Length == 2)
799 string xVal = parts[0].Trim();
800 string yVal = parts[1].Trim();
801 x = Convert.ToSingle(xVal, CultureInfo.InvariantCulture);
802 y = Convert.ToSingle(yVal, CultureInfo.InvariantCulture);
804 else if (parts.Length > 2)
806 string xVal = parts[0].Trim();
807 string yVal = parts[1].Trim();
808 x = Convert.ToSingle(xVal, CultureInfo.InvariantCulture);
809 y = Convert.ToSingle(yVal, CultureInfo.InvariantCulture);
812 for (
int i = 2; i < parts.Length; i++)
814 line = line + parts[i].Trim();
820 private static void GetParams(
char[] partsDelimiter, ref
string line,
int startLength, ref PointF[] points)
822 line = line.Remove(0, startLength);
823 string[] parts = line.Split(partsDelimiter);
824 if (parts.Length > 1 && parts.Length % 2 == 0)
826 points =
new PointF[parts.Length / 2];
827 for (
int i = 0; i < parts.Length; i = i + 2)
829 string xVal = parts[i].Trim();
830 string yVal = parts[i+1].Trim();
831 float x = Convert.ToSingle(xVal, CultureInfo.InvariantCulture);
832 float y = Convert.ToSingle(yVal, CultureInfo.InvariantCulture);
833 PointF point =
new PointF(x, y);
834 points[i / 2] = point;
841 private Bitmap ImageHttpRequest(
string url)
845 WebRequest request = HttpWebRequest.Create(url);
847 using (HttpWebResponse response = (HttpWebResponse)(request).GetResponse())
849 if (response.StatusCode == HttpStatusCode.OK)
851 using (Stream s = response.GetResponseStream())
853 Bitmap image =
new Bitmap(s);
bool AsyncConvertUrl(UUID id, string url, string extraParams)
IDynamicTexture ConvertData(string bodyData, string extraParams)
void GetDrawStringSize(string text, string fontName, int fontSize, out double xSize, out double ySize)
void Close()
This is the inverse to Initialise. After a Close(), this instance won't be usable anymore...
void PostInitialise()
This is called exactly once after all the shared region-modules have been instanciated and IRegionMod...
void RegionLoaded(Scene scene)
This will be called once for every scene loaded. In a shared module this will be multiple times in on...
void RemoveRegion(Scene scene)
This is called whenever a Scene is removed. For shared modules, this can happen several times...
bool AsyncConvertData(UUID id, string bodyData, string extraParams)
bool SupportsAsynchronous()
void AddRegion(Scene scene)
This is called whenever a Scene is added. For shared modules, this can happen several times...
void Initialise(IConfigSource config)
This is called to initialize the region module. For shared modules, this is called exactly once...
IDynamicTexture ConvertUrl(string url, string extraParams)