WebBrowserComponents.Mod 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. MODULE WebBrowserComponents; (** AUTHOR "Simon L. Keel"; PURPOSE "components used by the WebBrowser-modules"; *)
  2. IMPORT
  3. Strings, WMStandardComponents, WMGraphics, WMRectangles, WMEvents, WebHTTP, NewHTTPClient, Streams, Files,
  4. Raster, Codecs, KernelLog, WMComponents, WMTextView, Texts, TextUtilities, WMWindowManager,
  5. XML, SVG, SVGLoader;
  6. CONST
  7. verbose = TRUE;
  8. MaxHTTPConnections = 16;
  9. MaxHTTPConnectionPerServer = 3;
  10. TYPE
  11. String = Strings.String;
  12. VisualComponent = WMComponents.VisualComponent;
  13. SVGPanel* = OBJECT(VisualComponent)
  14. VAR
  15. img : SVG.Document;
  16. PROCEDURE & New*(svg: XML.Element);
  17. BEGIN
  18. Init;
  19. IF verbose THEN KernelLog.String("---Rendering SVG... "); END;
  20. img := SVGLoader.LoadSVGEmbedded(svg);
  21. IF img # NIL THEN
  22. bounds.SetExtents(img.width, img.height);
  23. IF verbose THEN KernelLog.String("done."); KernelLog.Ln(); END;
  24. ELSE
  25. bounds.SetExtents(15, 15);
  26. IF verbose THEN KernelLog.String("failed."); KernelLog.Ln(); END;
  27. END
  28. END New;
  29. PROCEDURE DrawBackground*(canvas : WMGraphics.Canvas);
  30. VAR
  31. w, h : LONGINT;
  32. BEGIN
  33. DrawBackground^(canvas);
  34. w := bounds.GetWidth();
  35. h := bounds.GetHeight();
  36. IF img # NIL THEN
  37. canvas.ScaleImage(img, WMRectangles.MakeRect(0, 0, img.width, img.height), WMRectangles.MakeRect(0, 0, w, h), WMGraphics.ModeCopy, 2)
  38. ELSE
  39. canvas.Line(0, 0, w-1, 0, 0FFH, WMGraphics.ModeSrcOverDst);
  40. canvas.Line(0, 0, 0, h-1, 0FFH, WMGraphics.ModeSrcOverDst);
  41. canvas.Line(0, h-1, w-1, h-1, 0FFH, WMGraphics.ModeSrcOverDst);
  42. canvas.Line(w-1, 0, w-1, h-1, 0FFH, WMGraphics.ModeSrcOverDst);
  43. canvas.Line(0, 0, w-1, h-1, 0FFH, WMGraphics.ModeSrcOverDst);
  44. canvas.Line(0, h-1, w-1, 0, 0FFH, WMGraphics.ModeSrcOverDst);
  45. END;
  46. END DrawBackground;
  47. END SVGPanel;
  48. SVGLinkPanel* = OBJECT(SVGPanel)
  49. VAR
  50. onClick : WMEvents.EventSource;
  51. msg : ANY;
  52. PROCEDURE & Create*(svg: XML.Element; loadLink : WMEvents.EventListener; msg : ANY);
  53. BEGIN
  54. New(svg);
  55. NEW(onClick, SELF, NIL, NIL, SELF.StringToCompCommand);
  56. events.Add(onClick);
  57. onClick.Add(loadLink);
  58. SELF.msg := msg;
  59. SetPointerInfo(manager.pointerLink);
  60. END Create;
  61. PROCEDURE PointerDown*(x, y: LONGINT; keys : SET);
  62. BEGIN
  63. onClick.Call(msg);
  64. PointerDown^(x, y, keys);
  65. END PointerDown;
  66. END SVGLinkPanel;
  67. (** just shows an image, stretches the image to fit to the property "bounds" (initial size = image size) *)
  68. StretchImagePanel* = OBJECT(VisualComponent)
  69. VAR
  70. img : WMGraphics.Image;
  71. PROCEDURE & New*(rc : ResourceConnection; url : String; x, y : LONGINT);
  72. BEGIN
  73. Init;
  74. IF rc = NIL THEN
  75. rc := GetResourceConnection(url);
  76. END;
  77. IF (rc # NIL) & (rc.reader # NIL) THEN
  78. IF verbose THEN KernelLog.String("---Loading StretchImagePanel. Url: "); KernelLog.String(rc.url^); KernelLog.String("... "); END;
  79. IF ~Strings.StartsWith2("image/", rc.mimeType^) THEN rc.mimeType := GetMimeType(rc.url^) END;
  80. img := LoadImage(rc.reader, rc.mimeType^, rc.url^);
  81. IF img # NIL THEN
  82. IF (x < 0) OR (y < 0) THEN
  83. x := img.width;
  84. y := img.height;
  85. END;
  86. bounds.SetExtents(x, y);
  87. END;
  88. IF verbose THEN KernelLog.String("done."); KernelLog.Ln(); END;
  89. END;
  90. IF (rc = NIL) OR (rc.reader = NIL) OR (img = NIL) THEN
  91. fillColor.Set(0FFFFFFFFH);
  92. IF (x < 0) OR (y < 0) THEN
  93. x := 15;
  94. y := 15;
  95. END;
  96. bounds.SetExtents(x, y);
  97. END;
  98. IF rc # NIL THEN rc.Release() END;
  99. END New;
  100. PROCEDURE DrawBackground*(canvas : WMGraphics.Canvas);
  101. VAR
  102. w, h : LONGINT;
  103. BEGIN
  104. DrawBackground^(canvas);
  105. w := bounds.GetWidth();
  106. h := bounds.GetHeight();
  107. IF img # NIL THEN
  108. canvas.ScaleImage(img, WMRectangles.MakeRect(0, 0, img.width, img.height), WMRectangles.MakeRect(0, 0, w, h), WMGraphics.ModeCopy, 2)
  109. ELSE
  110. canvas.Line(0, 0, w-1, 0, 0FFH, WMGraphics.ModeSrcOverDst);
  111. canvas.Line(0, 0, 0, h-1, 0FFH, WMGraphics.ModeSrcOverDst);
  112. canvas.Line(0, h-1, w-1, h-1, 0FFH, WMGraphics.ModeSrcOverDst);
  113. canvas.Line(w-1, 0, w-1, h-1, 0FFH, WMGraphics.ModeSrcOverDst);
  114. canvas.Line(0, 0, w-1, h-1, 0FFH, WMGraphics.ModeSrcOverDst);
  115. canvas.Line(0, h-1, w-1, 0, 0FFH, WMGraphics.ModeSrcOverDst);
  116. END;
  117. END DrawBackground;
  118. END StretchImagePanel;
  119. StretchImageLinkPanel* = OBJECT(StretchImagePanel)
  120. VAR
  121. onClick : WMEvents.EventSource;
  122. msg : ANY;
  123. PROCEDURE & Create*(rc : ResourceConnection; url : String; x, y : LONGINT; loadLink : WMEvents.EventListener; msg : ANY);
  124. BEGIN
  125. New(rc, url, x, y);
  126. NEW(onClick, SELF, NIL, NIL, SELF.StringToCompCommand);
  127. events.Add(onClick);
  128. onClick.Add(loadLink);
  129. SELF.msg := msg;
  130. SetPointerInfo(manager.pointerLink);
  131. END Create;
  132. PROCEDURE PointerDown*(x, y: LONGINT; keys : SET);
  133. BEGIN
  134. onClick.Call(msg);
  135. PointerDown^(x, y, keys);
  136. END PointerDown;
  137. END StretchImageLinkPanel;
  138. TileImagePanel* = OBJECT(VisualComponent)
  139. VAR
  140. img : WMGraphics.Image;
  141. PROCEDURE & New*(rc : ResourceConnection; url : String);
  142. BEGIN
  143. Init;
  144. alignment.Set(WMComponents.AlignClient);
  145. IF rc = NIL THEN
  146. rc := GetResourceConnection(url);
  147. END;
  148. IF (rc # NIL) & (rc.reader # NIL) THEN
  149. IF verbose THEN KernelLog.String("---Loading TileImagePanel. Url: "); KernelLog.String(rc.url^); KernelLog.String("... "); END;
  150. IF ~Strings.StartsWith2("image/", rc.mimeType^) THEN rc.mimeType := GetMimeType(rc.url^) END;
  151. img := LoadImage(rc.reader, rc.mimeType^, rc.url^);
  152. IF verbose THEN KernelLog.String("done."); KernelLog.Ln(); END;
  153. END;
  154. IF rc # NIL THEN rc.Release() END;
  155. END New;
  156. PROCEDURE DrawBackground*(canvas : WMGraphics.Canvas);
  157. VAR
  158. w, h, i, j, wCnt, hCnt : LONGINT;
  159. BEGIN
  160. DrawBackground^(canvas);
  161. IF img # NIL THEN
  162. w := bounds.GetWidth();
  163. h := bounds.GetHeight();
  164. wCnt := w DIV img.width;
  165. IF (wCnt * img.width) # w THEN INC(wCnt); END;
  166. hCnt := h DIV img.height;
  167. IF (hCnt * img.height) # h THEN INC(hCnt); END;
  168. FOR i := 1 TO wCnt DO
  169. FOR j := 1 TO hCnt DO
  170. canvas.DrawImage((i-1)*img.width, (j-1)*img.height, img, WMGraphics.ModeSrcOverDst);
  171. END;
  172. END;
  173. END
  174. END DrawBackground;
  175. END TileImagePanel;
  176. HR* = OBJECT(VisualComponent)
  177. VAR
  178. x : LONGINT;
  179. PROCEDURE & New*(x : LONGINT);
  180. BEGIN
  181. Init;
  182. ParentTvWidthChanged(x);
  183. END New;
  184. PROCEDURE ParentTvWidthChanged*(x : LONGINT);
  185. BEGIN
  186. DEC(x, 30);
  187. IF x < 10 THEN x := 10 END;
  188. SELF.x := x;
  189. bounds.SetExtents(x, 2);
  190. END ParentTvWidthChanged;
  191. PROCEDURE DrawBackground*(canvas : WMGraphics.Canvas);
  192. BEGIN
  193. DrawBackground^(canvas);
  194. canvas.Line(0, 0, x-1, 0, LONGINT(0808080FFH), WMGraphics.ModeSrcOverDst);
  195. canvas.Line(0, 1, x-1, 1, LONGINT(0C0C0C0FFH), WMGraphics.ModeSrcOverDst);
  196. END DrawBackground;
  197. END HR;
  198. ShortText* = OBJECT(VisualComponent)
  199. VAR
  200. textView : WMTextView.TextView;
  201. PROCEDURE & New*(txt : ARRAY OF CHAR);
  202. VAR
  203. errorText : Texts.Text;
  204. textWriter : TextUtilities.TextWriter;
  205. BEGIN
  206. Init;
  207. NEW(textView);
  208. textView.alignment.Set(WMComponents.AlignClient);
  209. NEW(errorText);
  210. NEW(textWriter, errorText);
  211. textWriter.SetFontSize(20);
  212. textWriter.SetVerticalOffset(20);
  213. textWriter.String(txt);
  214. textWriter.Update;
  215. textView.SetText(errorText);
  216. AddContent(textView);
  217. alignment.Set(WMComponents.AlignClient);
  218. END New;
  219. END ShortText;
  220. TextPanel* = OBJECT(VisualComponent)
  221. PROCEDURE & New*(rc : ResourceConnection; url : String);
  222. VAR
  223. vScrollbar : WMStandardComponents.Scrollbar;
  224. hScrollbar : WMStandardComponents.Scrollbar;
  225. tv : WMTextView.TextView;
  226. isoDecoder : Codecs.TextDecoder;
  227. result : WORD;
  228. BEGIN
  229. Init;
  230. takesFocus.Set(FALSE);
  231. alignment.Set(WMComponents.AlignClient);
  232. NEW(vScrollbar);
  233. vScrollbar.alignment.Set(WMComponents.AlignRight);
  234. AddContent(vScrollbar);
  235. NEW(hScrollbar);
  236. hScrollbar.alignment.Set(WMComponents.AlignBottom);
  237. hScrollbar.vertical.Set(FALSE);
  238. AddContent(hScrollbar);
  239. IF rc = NIL THEN
  240. rc := GetResourceConnection(url);
  241. END;
  242. IF (rc # NIL) & (rc.reader # NIL) THEN
  243. IF verbose THEN KernelLog.String("---Loading TextPanel. Url: "); KernelLog.String(rc.url^); KernelLog.String("... "); END;
  244. NEW(tv);
  245. tv.alignment.Set(WMComponents.AlignClient);
  246. tv.SetScrollbars(hScrollbar, vScrollbar);
  247. AddContent(tv);
  248. isoDecoder := Codecs.GetTextDecoder("ISO8859-1");
  249. isoDecoder.Open(rc.reader, result);
  250. tv.SetText(isoDecoder.GetText());
  251. tv.cursor.SetPosition(0);
  252. IF verbose THEN KernelLog.String("done."); KernelLog.Ln(); END;
  253. END;
  254. IF rc # NIL THEN rc.Release() END;
  255. END New;
  256. END TextPanel;
  257. HTTPConnectionPool* = OBJECT
  258. VAR
  259. connection : ARRAY MaxHTTPConnections OF ResourceConnection;
  260. conCnt : LONGINT;
  261. (*logW : MultiLogger.LogWindow;
  262. log : Streams.Writer;*)
  263. PROCEDURE & Init*;
  264. BEGIN
  265. conCnt := 0;
  266. (*NEW(logW, "HTTPConnectionPool", log);*)
  267. END Init;
  268. PROCEDURE Get*(url : String) : ResourceConnection;
  269. BEGIN {EXCLUSIVE}
  270. RETURN PrivateGet(url);
  271. END Get;
  272. PROCEDURE PrivateGet(url : String) : ResourceConnection;
  273. VAR
  274. server, newServer : String;
  275. index : LONGINT;
  276. i : LONGINT;
  277. con : ResourceConnection;
  278. charset: WebHTTP.AdditionalField;
  279. reader : Streams.Reader;
  280. result : WORD;
  281. cnt : LONGINT;
  282. BEGIN
  283. server := GetServer(url^);
  284. AWAIT((conCnt < MaxHTTPConnections) & (ServerCnt(server) < MaxHTTPConnectionPerServer));
  285. index := -1; i := 0;
  286. WHILE((index = -1) & (i < MaxHTTPConnections)) DO
  287. (* search for non-busy connection of the same server... *)
  288. IF (connection[i] # NIL) & (connection[i].server^ = server^) & (~connection[i].busy) THEN
  289. index := i;
  290. END;
  291. (* ... if none is found, search for empty index *)
  292. IF (i = MaxHTTPConnections - 1) & (index = -1) THEN
  293. i := 0;
  294. WHILE((index = -1) & (i < MaxHTTPConnections)) DO
  295. IF connection[i] = NIL THEN
  296. index := i;
  297. END;
  298. INC(i);
  299. END;
  300. (* ... if none is found, take the next non-busy connection. *)
  301. IF index = -1 THEN
  302. i := 0;
  303. WHILE((index = -1) & (i < MaxHTTPConnections)) DO
  304. IF ~connection[i].busy THEN
  305. index := i;
  306. END;
  307. INC(i);
  308. END;
  309. END;
  310. ASSERT(index >= 0);
  311. END;
  312. INC(i);
  313. END;
  314. ASSERT(index >= 0);
  315. (*log.String("Get: "); log.String(url^); log.String(" Index: "); log.Int(index, 0); log.Ln(); log.Update();*)
  316. con := connection[index];
  317. IF con = NIL THEN
  318. NEW(connection[index]);
  319. con := connection[index];
  320. con.index := index;
  321. con.server := server;
  322. NEW(con.http);
  323. con.http.requestHeader.useragent := "BimBrowser (bluebottle.ethz.ch)";
  324. IF Strings.Pos("google.", url^) # -1 THEN (* only to get UTF-8 charset *)
  325. con.http.requestHeader.useragent := "Mozilla/5.0";
  326. END;
  327. NEW(charset);
  328. charset.key := "Accept-Charset:";
  329. charset.value := "UTF-8,ISO-8859-1";
  330. con.http.requestHeader.additionalFields := charset;
  331. END;
  332. con.busy := TRUE;
  333. cnt := 0;
  334. LOOP
  335. con.http.Get(url^, TRUE, reader, result);
  336. IF (cnt < 16) & (result = 0) & ((con.http.responseHeader.statuscode >= 301) & (con.http.responseHeader.statuscode <= 303)) THEN (* "Moved" or "See Other" *)
  337. IF Strings.Pos("://", con.http.responseHeader.location) = -1 THEN
  338. IF ~Strings.StartsWith2("/", con.http.responseHeader.location) THEN
  339. url := Strings.ConcatToNew(server^, "/");
  340. url := Strings.ConcatToNew(url^, con.http.responseHeader.location);
  341. ELSE
  342. url := Strings.ConcatToNew(server^, con.http.responseHeader.location);
  343. END;
  344. ELSE
  345. url := Strings.NewString(con.http.responseHeader.location);
  346. newServer := GetServer(con.http.responseHeader.location);
  347. IF server^ # newServer^ THEN
  348. con.busy := FALSE;
  349. RETURN PrivateGet(url);
  350. END;
  351. END;
  352. IF verbose THEN KernelLog.String("---Redirecting to "); KernelLog.String(url^); KernelLog.Ln(); END;
  353. WHILE reader.Get() # 0X DO END;
  354. INC(cnt);
  355. ELSE
  356. EXIT;
  357. END;
  358. END;
  359. con.url := url;
  360. con.mimeType := Strings.NewString(con.http.responseHeader.contenttype);
  361. Strings.TrimWS(con.mimeType^);
  362. con.reader := reader;
  363. con.released := FALSE;
  364. IF result # 0 THEN
  365. con.busy := FALSE;
  366. RETURN NIL;
  367. ELSE
  368. INC(conCnt);
  369. RETURN con;
  370. END;
  371. END PrivateGet;
  372. PROCEDURE Release(rc : ResourceConnection);
  373. BEGIN {EXCLUSIVE}
  374. connection[rc.index].busy := FALSE;
  375. DEC(conCnt);
  376. END Release;
  377. PROCEDURE ServerCnt(server : String) : LONGINT;
  378. VAR
  379. cnt, i : LONGINT;
  380. BEGIN
  381. cnt := 0;
  382. FOR i := 0 TO MaxHTTPConnections - 1 DO
  383. IF (connection[i] # NIL) & (connection[i].server^ = server^) & (connection[i].busy) THEN INC(cnt) END;
  384. END;
  385. RETURN cnt;
  386. END ServerCnt;
  387. PROCEDURE GetServer(VAR url : ARRAY OF CHAR) : String;
  388. VAR
  389. end : SIZE;
  390. BEGIN
  391. end := Strings.IndexOfByte('/', Strings.Pos("://", url) + 3, url);
  392. IF end = -1 THEN end := Strings.Length(url) END;
  393. RETURN Strings.Substring(0, end, url);
  394. END GetServer;
  395. END HTTPConnectionPool;
  396. ResourceConnection* = OBJECT
  397. VAR
  398. url- : String;
  399. mimeType- : String;
  400. reader- : Streams.Reader;
  401. http : NewHTTPClient.HTTPConnection;
  402. busy : BOOLEAN;
  403. index : LONGINT;
  404. server : String;
  405. released : BOOLEAN;
  406. PROCEDURE Stop*;
  407. BEGIN {EXCLUSIVE}
  408. IF ~released & (http # NIL) THEN
  409. http.Close();
  410. server := Strings.NewString("");
  411. END;
  412. END Stop;
  413. PROCEDURE Release*;
  414. BEGIN {EXCLUSIVE}
  415. released := TRUE;
  416. IF http # NIL THEN
  417. httpConnectionPool.Release(SELF);
  418. END;
  419. END Release;
  420. END ResourceConnection;
  421. VAR
  422. manager : WMWindowManager.WindowManager;
  423. httpConnectionPool* : HTTPConnectionPool;
  424. PROCEDURE GetResourceConnection*(url : String) : ResourceConnection;
  425. VAR
  426. pos : SIZE;
  427. protocol : String;
  428. filename : String;
  429. connection : ResourceConnection;
  430. file : Files.File;
  431. fileReader : Files.Reader;
  432. BEGIN
  433. Strings.TrimWS(url^);
  434. pos := Strings.Pos("://", url^);
  435. IF pos = -1 THEN
  436. IF verbose THEN KernelLog.String("Unknown Protocol: "); KernelLog.String(url^); KernelLog.Ln(); END;
  437. RETURN NIL;
  438. END;
  439. protocol := Strings.Substring(0, pos, url^);
  440. IF (pos + 3) >= Strings.Length(url^) THEN
  441. IF verbose THEN KernelLog.String("Bad URL: "); KernelLog.String(url^); KernelLog.Ln(); END;
  442. RETURN NIL;
  443. END;
  444. filename := Strings.Substring2(pos+3, url^);
  445. ClearFilename(filename^);
  446. IF protocol^ = "http" THEN
  447. RETURN httpConnectionPool.Get(url);
  448. ELSIF protocol^ = "file" THEN
  449. file := Files.Old(filename^);
  450. IF file = NIL THEN
  451. IF verbose THEN KernelLog.String("file not found: "); KernelLog.String(url^); KernelLog.Ln(); END;
  452. RETURN NIL;
  453. END;
  454. Files.OpenReader(fileReader, file, 0);
  455. NEW(connection);
  456. connection.url := url;
  457. connection.mimeType := GetMimeType(filename^);
  458. connection.reader := fileReader;
  459. RETURN connection;
  460. ELSE
  461. IF verbose THEN KernelLog.String("Unknown Protocol: "); KernelLog.String(protocol^); KernelLog.Ln(); END;
  462. RETURN NIL;
  463. END;
  464. END GetResourceConnection;
  465. PROCEDURE ClearFilename( VAR name: ARRAY OF CHAR ); (* strip positioning info appended to filename *)
  466. VAR i: LONGINT;
  467. BEGIN
  468. i := 0;
  469. LOOP
  470. IF name[i] < '.' THEN name[i] := 0X END;
  471. IF name[i] = 0X THEN EXIT END;
  472. INC( i );
  473. IF i >= LEN( name ) THEN EXIT END
  474. END
  475. END ClearFilename;
  476. PROCEDURE GetMimeType(VAR filename : ARRAY OF CHAR) : String;
  477. VAR
  478. dotPos : SIZE;
  479. appendix : String;
  480. BEGIN
  481. Strings.TrimWS(filename);
  482. dotPos := Strings.LastIndexOfByte2('.', filename);
  483. IF (dotPos = -1) OR (dotPos = Strings.Length(filename) - 1) THEN
  484. RETURN Strings.NewString(filename);
  485. END;
  486. appendix := Strings.Substring2(dotPos + 1, filename);
  487. Strings.LowerCase(appendix^);
  488. IF appendix^ = "html" THEN RETURN Strings.NewString("text/html"); END;
  489. IF appendix^ = "htm" THEN RETURN Strings.NewString("text/html"); END;
  490. IF appendix^ = "txt" THEN RETURN Strings.NewString("text/plain"); END;
  491. IF appendix^ = "jpg" THEN RETURN Strings.NewString("image/jpeg"); END;
  492. IF appendix^ = "jpeg" THEN RETURN Strings.NewString("image/jpeg"); END;
  493. IF appendix^ = "jpe" THEN RETURN Strings.NewString("image/jpeg"); END;
  494. IF appendix^ = "jp2" THEN RETURN Strings.NewString("image/jp2"); END;
  495. IF appendix^ = "png" THEN RETURN Strings.NewString("image/png"); END;
  496. IF appendix^ = "bmp" THEN RETURN Strings.NewString("image/bmp"); END;
  497. IF appendix^ = "gif" THEN RETURN Strings.NewString("image/gif"); END;
  498. IF appendix^ = "svg" THEN RETURN Strings.NewString("image/svg+xml"); END;
  499. IF appendix^ = "xml" THEN RETURN Strings.NewString("application/xml"); END;
  500. IF appendix^ = "pdf" THEN RETURN Strings.NewString("application/pdf"); END;
  501. RETURN appendix;
  502. END GetMimeType;
  503. PROCEDURE LoadImage*(reader : Streams.Reader; mimeType : ARRAY OF CHAR; name : ARRAY OF CHAR): WMGraphics.Image;
  504. VAR
  505. img : WMGraphics.Image;
  506. res: WORD; w, h, x : LONGINT;
  507. decoder : Codecs.ImageDecoder;
  508. ext : String;
  509. PROCEDURE GetExtensionForMimeType(VAR mimeType : ARRAY OF CHAR) : String;
  510. BEGIN
  511. IF Strings.StartsWith2("image/jpeg", mimeType) THEN RETURN Strings.NewString("JPG"); END;
  512. IF Strings.StartsWith2("image/jp2", mimeType) THEN RETURN Strings.NewString("JP2"); END;
  513. IF Strings.StartsWith2("image/png", mimeType) THEN RETURN Strings.NewString("PNG"); END;
  514. IF Strings.StartsWith2("image/bmp", mimeType) THEN RETURN Strings.NewString("BMP"); END;
  515. IF Strings.StartsWith2("image/gif", mimeType) THEN RETURN Strings.NewString("GIF"); END;
  516. IF Strings.StartsWith2("image/svg+xml", mimeType) THEN RETURN Strings.NewString("SVG"); END;
  517. RETURN Strings.NewString("");
  518. END GetExtensionForMimeType;
  519. BEGIN
  520. IF reader = NIL THEN RETURN NIL END;
  521. ext := GetExtensionForMimeType(mimeType);
  522. decoder := Codecs.GetImageDecoder(ext^);
  523. IF decoder = NIL THEN
  524. KernelLog.String("No decoder found for "); KernelLog.String(mimeType); KernelLog.Ln;
  525. RETURN NIL
  526. END;
  527. decoder.Open(reader, res);
  528. IF res = 0 THEN
  529. decoder.GetImageInfo(w, h, x, x);
  530. NEW(img);
  531. Raster.Create(img, w, h, Raster.BGRA8888);
  532. decoder.Render(img);
  533. NEW(img.key, LEN(name)); COPY(name, img.key^);
  534. END;
  535. RETURN img
  536. END LoadImage;
  537. BEGIN
  538. manager := WMWindowManager.GetDefaultManager();
  539. NEW(httpConnectionPool);
  540. END WebBrowserComponents.