clockwerk-opensim-stable – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 /*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27  
28 using System;
29 using System.Drawing;
30 using System.Drawing.Imaging;
31 using System.Globalization;
32 using System.IO;
33 using System.Linq;
34 using System.Net;
35 using Nini.Config;
36 using OpenMetaverse;
37 using OpenMetaverse.Imaging;
38 using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
39 using OpenSim.Region.Framework.Interfaces;
40 using OpenSim.Region.Framework.Scenes;
41 using log4net;
42 using System.Reflection;
43 using Mono.Addins;
44  
45 //using Cairo;
46  
47 namespace OpenSim.Region.CoreModules.Scripting.VectorRender
48 {
49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "VectorRenderModule")]
50 public class VectorRenderModule : ISharedRegionModule, IDynamicTextureRender
51 {
52 // These fields exist for testing purposes, please do not remove.
53 // private static bool s_flipper;
54 // private static byte[] s_asset1Data;
55 // private static byte[] s_asset2Data;
56  
57 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
58  
59 private Scene m_scene;
60 private IDynamicTextureManager m_textureManager;
61  
62 private Graphics m_graph;
63 private string m_fontName = "Arial";
64  
65 public VectorRenderModule()
66 {
67 }
68  
69 #region IDynamicTextureRender Members
70  
71 public string GetContentType()
72 {
73 return "vector";
74 }
75  
76 public string GetName()
77 {
78 return Name;
79 }
80  
81 public bool SupportsAsynchronous()
82 {
83 return true;
84 }
85  
86 // public bool AlwaysIdenticalConversion(string bodyData, string extraParams)
87 // {
88 // string[] lines = GetLines(bodyData);
89 // return lines.Any((str, r) => str.StartsWith("Image"));
90 // }
91  
92 public IDynamicTexture ConvertUrl(string url, string extraParams)
93 {
94 return null;
95 }
96  
97 public IDynamicTexture ConvertData(string bodyData, string extraParams)
98 {
99 return Draw(bodyData, extraParams);
100 }
101  
102 public bool AsyncConvertUrl(UUID id, string url, string extraParams)
103 {
104 return false;
105 }
106  
107 public bool AsyncConvertData(UUID id, string bodyData, string extraParams)
108 {
109 if (m_textureManager == null)
110 {
111 m_log.Warn("[VECTORRENDERMODULE]: No texture manager. Can't function");
112 return false;
113 }
114 // XXX: This isn't actually being done asynchronously!
115 m_textureManager.ReturnData(id, ConvertData(bodyData, extraParams));
116  
117 return true;
118 }
119  
120 public void GetDrawStringSize(string text, string fontName, int fontSize,
121 out double xSize, out double ySize)
122 {
123 lock (this)
124 {
125 using (Font myFont = new Font(fontName, fontSize))
126 {
127 SizeF stringSize = new SizeF();
128  
129 // XXX: This lock may be unnecessary.
130 lock (m_graph)
131 {
132 stringSize = m_graph.MeasureString(text, myFont);
133 xSize = stringSize.Width;
134 ySize = stringSize.Height;
135 }
136 }
137 }
138 }
139  
140 #endregion
141  
142 #region ISharedRegionModule Members
143  
144 public void Initialise(IConfigSource config)
145 {
146 IConfig cfg = config.Configs["VectorRender"];
147 if (null != cfg)
148 {
149 m_fontName = cfg.GetString("font_name", m_fontName);
150 }
151 m_log.DebugFormat("[VECTORRENDERMODULE]: using font \"{0}\" for text rendering.", m_fontName);
152  
153 // We won't dispose of these explicitly since this module is only removed when the entire simulator
154 // is shut down.
155 Bitmap bitmap = new Bitmap(1024, 1024, PixelFormat.Format32bppArgb);
156 m_graph = Graphics.FromImage(bitmap);
157 }
158  
159 public void PostInitialise()
160 {
161 }
162  
163 public void AddRegion(Scene scene)
164 {
165 if (m_scene == null)
166 {
167 m_scene = scene;
168 }
169 }
170  
171 public void RegionLoaded(Scene scene)
172 {
173 if (m_textureManager == null && m_scene == scene)
174 {
175 m_textureManager = m_scene.RequestModuleInterface<IDynamicTextureManager>();
176 if (m_textureManager != null)
177 {
178 m_textureManager.RegisterRender(GetContentType(), this);
179 }
180 }
181 }
182  
183 public void RemoveRegion(Scene scene)
184 {
185 }
186  
187 public void Close()
188 {
189 }
190  
191 public string Name
192 {
193 get { return "VectorRenderModule"; }
194 }
195  
196 public Type ReplaceableInterface
197 {
198 get { return null; }
199 }
200  
201 #endregion
202  
203 private IDynamicTexture Draw(string data, string extraParams)
204 {
205 // We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha
206 // we will now support multiple comma seperated params in the form width:256,height:512,alpha:255
207 int width = 256;
208 int height = 256;
209 int alpha = 255; // 0 is transparent
210 Color bgColor = Color.White; // Default background color
211 char altDataDelim = ';';
212  
213 char[] paramDelimiter = { ',' };
214 char[] nvpDelimiter = { ':' };
215  
216 extraParams = extraParams.Trim();
217 extraParams = extraParams.ToLower();
218  
219 string[] nvps = extraParams.Split(paramDelimiter);
220  
221 int temp = -1;
222 foreach (string pair in nvps)
223 {
224 string[] nvp = pair.Split(nvpDelimiter);
225 string name = "";
226 string value = "";
227  
228 if (nvp[0] != null)
229 {
230 name = nvp[0].Trim();
231 }
232  
233 if (nvp.Length == 2)
234 {
235 value = nvp[1].Trim();
236 }
237  
238 switch (name)
239 {
240 case "width":
241 temp = parseIntParam(value);
242 if (temp != -1)
243 {
244 if (temp < 1)
245 {
246 width = 1;
247 }
248 else if (temp > 2048)
249 {
250 width = 2048;
251 }
252 else
253 {
254 width = temp;
255 }
256 }
257 break;
258 case "height":
259 temp = parseIntParam(value);
260 if (temp != -1)
261 {
262 if (temp < 1)
263 {
264 height = 1;
265 }
266 else if (temp > 2048)
267 {
268 height = 2048;
269 }
270 else
271 {
272 height = temp;
273 }
274 }
275 break;
276 case "alpha":
277 temp = parseIntParam(value);
278 if (temp != -1)
279 {
280 if (temp < 0)
281 {
282 alpha = 0;
283 }
284 else if (temp > 255)
285 {
286 alpha = 255;
287 }
288 else
289 {
290 alpha = temp;
291 }
292 }
293 // Allow a bitmap w/o the alpha component to be created
294 else if (value.ToLower() == "false") {
295 alpha = 256;
296 }
297 break;
298 case "bgcolor":
299 case "bgcolour":
300 int hex = 0;
301 if (Int32.TryParse(value, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out hex))
302 {
303 bgColor = Color.FromArgb(hex);
304 }
305 else
306 {
307 bgColor = Color.FromName(value);
308 }
309 break;
310 case "altdatadelim":
311 altDataDelim = value.ToCharArray()[0];
312 break;
313 case "":
314 // blank string has been passed do nothing just use defaults
315 break;
316 default: // this is all for backwards compat, all a bit ugly hopfully can be removed in future
317 // could be either set alpha or just an int
318 if (name == "setalpha")
319 {
320 alpha = 0; // set the texture to have transparent background (maintains backwards compat)
321 }
322 else
323 {
324 // this function used to accept an int on its own that represented both
325 // width and height, this is to maintain backwards compat, could be removed
326 // but would break existing scripts
327 temp = parseIntParam(name);
328 if (temp != -1)
329 {
330 if (temp > 1024)
331 temp = 1024;
332  
333 if (temp < 128)
334 temp = 128;
335  
336 width = temp;
337 height = temp;
338 }
339 }
340 break;
341 }
342 }
343  
344 Bitmap bitmap = null;
345 Graphics graph = null;
346 bool reuseable = false;
347  
348 try
349 {
350 // XXX: In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously,
351 // the native malloc heap can become corrupted, possibly due to a double free(). This may be due to
352 // bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX. These problems were
353 // seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1. They go away if disposal is perfomed
354 // under lock.
355 lock (this)
356 {
357 if (alpha == 256)
358 bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb);
359 else
360 bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
361  
362 graph = Graphics.FromImage(bitmap);
363  
364 // this is really just to save people filling the
365 // background color in their scripts, only do when fully opaque
366 if (alpha >= 255)
367 {
368 using (SolidBrush bgFillBrush = new SolidBrush(bgColor))
369 {
370 graph.FillRectangle(bgFillBrush, 0, 0, width, height);
371 }
372 }
373  
374 for (int w = 0; w < bitmap.Width; w++)
375 {
376 if (alpha <= 255)
377 {
378 for (int h = 0; h < bitmap.Height; h++)
379 {
380 bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h)));
381 }
382 }
383 }
384  
385 GDIDraw(data, graph, altDataDelim, out reuseable);
386 }
387  
388 byte[] imageJ2000 = new byte[0];
389  
390 // This code exists for testing purposes, please do not remove.
391 // if (s_flipper)
392 // imageJ2000 = s_asset1Data;
393 // else
394 // imageJ2000 = s_asset2Data;
395 //
396 // s_flipper = !s_flipper;
397  
398 try
399 {
400 imageJ2000 = OpenJPEG.EncodeFromImage(bitmap, true);
401 }
402 catch (Exception e)
403 {
404 m_log.ErrorFormat(
405 "[VECTORRENDERMODULE]: OpenJpeg Encode Failed. Exception {0}{1}",
406 e.Message, e.StackTrace);
407 }
408  
409 return new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture(
410 data, extraParams, imageJ2000, new Size(width, height), reuseable);
411 }
412 finally
413 {
414 // XXX: In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously,
415 // the native malloc heap can become corrupted, possibly due to a double free(). This may be due to
416 // bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX. These problems were
417 // seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1. They go away if disposal is perfomed
418 // under lock.
419 lock (this)
420 {
421 if (graph != null)
422 graph.Dispose();
423  
424 if (bitmap != null)
425 bitmap.Dispose();
426 }
427 }
428 }
429  
430 private int parseIntParam(string strInt)
431 {
432 int parsed;
433 try
434 {
435 parsed = Convert.ToInt32(strInt);
436 }
437 catch (Exception)
438 {
439 //Ckrinke: Add a WriteLine to remove the warning about 'e' defined but not used
440 // m_log.Debug("Problem with Draw. Please verify parameters." + e.ToString());
441 parsed = -1;
442 }
443  
444 return parsed;
445 }
446  
447 /*
448 private void CairoDraw(string data, System.Drawing.Graphics graph)
449 {
450 using (Win32Surface draw = new Win32Surface(graph.GetHdc()))
451 {
452 Context contex = new Context(draw);
453  
454 contex.Antialias = Antialias.None; //fastest method but low quality
455 contex.LineWidth = 7;
456 char[] lineDelimiter = { ';' };
457 char[] partsDelimiter = { ',' };
458 string[] lines = data.Split(lineDelimiter);
459  
460 foreach (string line in lines)
461 {
462 string nextLine = line.Trim();
463  
464 if (nextLine.StartsWith("MoveTO"))
465 {
466 float x = 0;
467 float y = 0;
468 GetParams(partsDelimiter, ref nextLine, ref x, ref y);
469 contex.MoveTo(x, y);
470 }
471 else if (nextLine.StartsWith("LineTo"))
472 {
473 float x = 0;
474 float y = 0;
475 GetParams(partsDelimiter, ref nextLine, ref x, ref y);
476 contex.LineTo(x, y);
477 contex.Stroke();
478 }
479 }
480 }
481 graph.ReleaseHdc();
482 }
483 */
484  
485 /// <summary>
486 /// Split input data into discrete command lines.
487 /// </summary>
488 /// <returns></returns>
489 /// <param name='data'></param>
490 /// <param name='dataDelim'></param>
491 private string[] GetLines(string data, char dataDelim)
492 {
493 char[] lineDelimiter = { dataDelim };
494 return data.Split(lineDelimiter);
495 }
496  
497 private void GDIDraw(string data, Graphics graph, char dataDelim, out bool reuseable)
498 {
499 reuseable = true;
500 Point startPoint = new Point(0, 0);
501 Point endPoint = new Point(0, 0);
502 Pen drawPen = null;
503 Font myFont = null;
504 SolidBrush myBrush = null;
505  
506 try
507 {
508 drawPen = new Pen(Color.Black, 7);
509 string fontName = m_fontName;
510 float fontSize = 14;
511 myFont = new Font(fontName, fontSize);
512 myBrush = new SolidBrush(Color.Black);
513  
514 char[] partsDelimiter = {','};
515  
516 foreach (string line in GetLines(data, dataDelim))
517 {
518 string nextLine = line.Trim();
519  
520 // m_log.DebugFormat("[VECTOR RENDER MODULE]: Processing line '{0}'", nextLine);
521  
522 //replace with switch, or even better, do some proper parsing
523 if (nextLine.StartsWith("MoveTo"))
524 {
525 float x = 0;
526 float y = 0;
527 GetParams(partsDelimiter, ref nextLine, 6, ref x, ref y);
528 startPoint.X = (int) x;
529 startPoint.Y = (int) y;
530 }
531 else if (nextLine.StartsWith("LineTo"))
532 {
533 float x = 0;
534 float y = 0;
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;
541 }
542 else if (nextLine.StartsWith("Text"))
543 {
544 nextLine = nextLine.Remove(0, 4);
545 nextLine = nextLine.Trim();
546 graph.DrawString(nextLine, myFont, myBrush, startPoint);
547 }
548 else if (nextLine.StartsWith("Image"))
549 {
550 // We cannot reuse any generated texture involving fetching an image via HTTP since that image
551 // can change.
552 reuseable = false;
553  
554 float x = 0;
555 float y = 0;
556 GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y);
557 endPoint.X = (int) x;
558 endPoint.Y = (int) y;
559  
560 using (Image image = ImageHttpRequest(nextLine))
561 {
562 if (image != null)
563 {
564 graph.DrawImage(image, (float)startPoint.X, (float)startPoint.Y, x, y);
565 }
566 else
567 {
568 using (Font errorFont = new Font(m_fontName,6))
569 {
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));
574 }
575  
576 graph.DrawRectangle(drawPen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y);
577 }
578 }
579  
580 startPoint.X += endPoint.X;
581 startPoint.Y += endPoint.Y;
582 }
583 else if (nextLine.StartsWith("Rectangle"))
584 {
585 float x = 0;
586 float y = 0;
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;
593 }
594 else if (nextLine.StartsWith("FillRectangle"))
595 {
596 float x = 0;
597 float y = 0;
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;
604 }
605 else if (nextLine.StartsWith("FillPolygon"))
606 {
607 PointF[] points = null;
608 GetParams(partsDelimiter, ref nextLine, 11, ref points);
609 graph.FillPolygon(myBrush, points);
610 }
611 else if (nextLine.StartsWith("Polygon"))
612 {
613 PointF[] points = null;
614 GetParams(partsDelimiter, ref nextLine, 7, ref points);
615 graph.DrawPolygon(drawPen, points);
616 }
617 else if (nextLine.StartsWith("Ellipse"))
618 {
619 float x = 0;
620 float y = 0;
621 GetParams(partsDelimiter, ref nextLine, 7, ref x, ref y);
622 endPoint.X = (int)x;
623 endPoint.Y = (int)y;
624 graph.DrawEllipse(drawPen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y);
625 startPoint.X += endPoint.X;
626 startPoint.Y += endPoint.Y;
627 }
628 else if (nextLine.StartsWith("FontSize"))
629 {
630 nextLine = nextLine.Remove(0, 8);
631 nextLine = nextLine.Trim();
632 fontSize = Convert.ToSingle(nextLine, CultureInfo.InvariantCulture);
633  
634 myFont.Dispose();
635 myFont = new Font(fontName, fontSize);
636 }
637 else if (nextLine.StartsWith("FontProp"))
638 {
639 nextLine = nextLine.Remove(0, 8);
640 nextLine = nextLine.Trim();
641  
642 string[] fprops = nextLine.Split(partsDelimiter);
643 foreach (string prop in fprops)
644 {
645  
646 switch (prop)
647 {
648 case "B":
649 if (!(myFont.Bold))
650 {
651 Font newFont = new Font(myFont, myFont.Style | FontStyle.Bold);
652 myFont.Dispose();
653 myFont = newFont;
654 }
655 break;
656 case "I":
657 if (!(myFont.Italic))
658 {
659 Font newFont = new Font(myFont, myFont.Style | FontStyle.Italic);
660 myFont.Dispose();
661 myFont = newFont;
662 }
663 break;
664 case "U":
665 if (!(myFont.Underline))
666 {
667 Font newFont = new Font(myFont, myFont.Style | FontStyle.Underline);
668 myFont.Dispose();
669 myFont = newFont;
670 }
671 break;
672 case "S":
673 if (!(myFont.Strikeout))
674 {
675 Font newFont = new Font(myFont, myFont.Style | FontStyle.Strikeout);
676 myFont.Dispose();
677 myFont = newFont;
678 }
679 break;
680 case "R":
681 // We need to place this newFont inside its own context so that the .NET compiler
682 // doesn't complain about a redefinition of an existing newFont, even though there is none
683 // The mono compiler doesn't produce this error.
684 {
685 Font newFont = new Font(myFont, FontStyle.Regular);
686 myFont.Dispose();
687 myFont = newFont;
688 }
689 break;
690 }
691 }
692 }
693 else if (nextLine.StartsWith("FontName"))
694 {
695 nextLine = nextLine.Remove(0, 8);
696 fontName = nextLine.Trim();
697 myFont.Dispose();
698 myFont = new Font(fontName, fontSize);
699 }
700 else if (nextLine.StartsWith("PenSize"))
701 {
702 nextLine = nextLine.Remove(0, 7);
703 nextLine = nextLine.Trim();
704 float size = Convert.ToSingle(nextLine, CultureInfo.InvariantCulture);
705 drawPen.Width = size;
706 }
707 else if (nextLine.StartsWith("PenCap"))
708 {
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")
714 end = false;
715 else if (cap[0].ToLower() == "end")
716 start = false;
717 else if (cap[0].ToLower() != "both")
718 return;
719 string type = cap[1].ToLower();
720  
721 if (end)
722 {
723 switch (type)
724 {
725 case "arrow":
726 drawPen.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
727 break;
728 case "round":
729 drawPen.EndCap = System.Drawing.Drawing2D.LineCap.RoundAnchor;
730 break;
731 case "diamond":
732 drawPen.EndCap = System.Drawing.Drawing2D.LineCap.DiamondAnchor;
733 break;
734 case "flat":
735 drawPen.EndCap = System.Drawing.Drawing2D.LineCap.Flat;
736 break;
737 }
738 }
739 if (start)
740 {
741 switch (type)
742 {
743 case "arrow":
744 drawPen.StartCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
745 break;
746 case "round":
747 drawPen.StartCap = System.Drawing.Drawing2D.LineCap.RoundAnchor;
748 break;
749 case "diamond":
750 drawPen.StartCap = System.Drawing.Drawing2D.LineCap.DiamondAnchor;
751 break;
752 case "flat":
753 drawPen.StartCap = System.Drawing.Drawing2D.LineCap.Flat;
754 break;
755 }
756 }
757 }
758 else if (nextLine.StartsWith("PenColour") || nextLine.StartsWith("PenColor"))
759 {
760 nextLine = nextLine.Remove(0, 9);
761 nextLine = nextLine.Trim();
762 int hex = 0;
763  
764 Color newColor;
765 if (Int32.TryParse(nextLine, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out hex))
766 {
767 newColor = Color.FromArgb(hex);
768 }
769 else
770 {
771 // this doesn't fail, it just returns black if nothing is found
772 newColor = Color.FromName(nextLine);
773 }
774  
775 myBrush.Color = newColor;
776 drawPen.Color = newColor;
777 }
778 }
779 }
780 finally
781 {
782 if (drawPen != null)
783 drawPen.Dispose();
784  
785 if (myFont != null)
786 myFont.Dispose();
787  
788 if (myBrush != null)
789 myBrush.Dispose();
790 }
791 }
792  
793 private static void GetParams(char[] partsDelimiter, ref string line, int startLength, ref float x, ref float y)
794 {
795 line = line.Remove(0, startLength);
796 string[] parts = line.Split(partsDelimiter);
797 if (parts.Length == 2)
798 {
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);
803 }
804 else if (parts.Length > 2)
805 {
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);
810  
811 line = "";
812 for (int i = 2; i < parts.Length; i++)
813 {
814 line = line + parts[i].Trim();
815 line = line + " ";
816 }
817 }
818 }
819  
820 private static void GetParams(char[] partsDelimiter, ref string line, int startLength, ref PointF[] points)
821 {
822 line = line.Remove(0, startLength);
823 string[] parts = line.Split(partsDelimiter);
824 if (parts.Length > 1 && parts.Length % 2 == 0)
825 {
826 points = new PointF[parts.Length / 2];
827 for (int i = 0; i < parts.Length; i = i + 2)
828 {
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;
835  
836 // m_log.DebugFormat("[VECTOR RENDER MODULE]: Got point {0}", points[i / 2]);
837 }
838 }
839 }
840  
841 private Bitmap ImageHttpRequest(string url)
842 {
843 try
844 {
845 WebRequest request = HttpWebRequest.Create(url);
846  
847 using (HttpWebResponse response = (HttpWebResponse)(request).GetResponse())
848 {
849 if (response.StatusCode == HttpStatusCode.OK)
850 {
851 using (Stream s = response.GetResponseStream())
852 {
853 Bitmap image = new Bitmap(s);
854 return image;
855 }
856 }
857 }
858 }
859 catch { }
860  
861 return null;
862 }
863 }
864 }