2
0

WMOberonFonts.Mod 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. MODULE WMOberonFonts; (** AUTHOR "TF"; PURPOSE "Support for oberon bitmap fonts"; *)
  2. IMPORT
  3. KernelLog, Streams, Files, WMGraphics, Raster, WMFontManager, Strings;
  4. CONST TraceImport = FALSE;
  5. TYPE
  6. Glyph = RECORD
  7. img : WMGraphics.Image;
  8. available : BOOLEAN;
  9. dx, x, y, w, h : LONGINT;
  10. END;
  11. Font* = OBJECT(WMGraphics.Font)
  12. VAR glyphs : ARRAY 256 OF Glyph;
  13. placeholderimg : WMGraphics.Image;
  14. idch, typech, famch, varch : CHAR;
  15. height, minX, maxX, minY, maxY, nofRuns : INTEGER;
  16. runs : ARRAY 32 OF RECORD beg, end : LONGINT END;
  17. (* map unicode to oberon *)
  18. PROCEDURE MapChars(VAR ch : LONGINT);
  19. BEGIN
  20. CASE ch OF
  21. 0C4H : ch := 128;
  22. | 0D6H : ch := 129;
  23. | 0DCH : ch := 130;
  24. | 0E4H : ch := 131;
  25. | 0F6H : ch := 132;
  26. | 0FCH : ch := 133;
  27. | 0E2H : ch := 134;
  28. | 0EAH : ch := 135;
  29. | 0EEH : ch := 136;
  30. | 0F4H : ch := 137;
  31. | 0FBH : ch := 138;
  32. | 0E0H : ch := 139;
  33. | 0E8H : ch := 140;
  34. | 0ECH : ch := 141;
  35. | 0F2H : ch := 142;
  36. | 0F9H : ch := 143;
  37. | 0E9H : ch := 144;
  38. | 0EBH : ch := 145;
  39. | 0EFH : ch := 146;
  40. | 0E7H : ch := 147;
  41. | 0E1H : ch := 148;
  42. | 0F1H : ch := 149;
  43. | 0DFH : ch := 150;
  44. | 0A3H : ch := 151;
  45. | 0B6H : ch := 152;
  46. | 0C7H : ch := 153;
  47. ELSE
  48. IF ch = 2030H THEN ch := 154
  49. ELSIF ch = 2013H THEN ch := 155
  50. END
  51. END;
  52. END MapChars;
  53. PROCEDURE &Init*;
  54. VAR mode : Raster.Mode; pix : Raster.Pixel;
  55. BEGIN
  56. Init^;
  57. NEW(placeholderimg); Raster.Create(placeholderimg, 16, 16, Raster.A1);
  58. Raster.InitMode(mode, Raster.srcCopy);
  59. Raster.SetRGBA(pix, 0, 0, 0, 0);
  60. Raster.Fill(placeholderimg, 0, 0, 15, 15, pix, mode)
  61. END Init;
  62. PROCEDURE GetGlyphMap*(code : LONGINT; VAR map : WMGraphics.Image);
  63. BEGIN
  64. MapChars(code);
  65. IF (code >= 0) & (code < 256) & (glyphs[code].available) & (glyphs[code].img # NIL) THEN
  66. map := glyphs[code].img
  67. ELSE map := placeholderimg
  68. END
  69. END GetGlyphMap;
  70. PROCEDURE HasChar*(code : LONGINT) : BOOLEAN;
  71. BEGIN
  72. MapChars(code);
  73. RETURN (code >= 0) & (code < 256) & (glyphs[code].available)
  74. END HasChar;
  75. PROCEDURE GetGlyphSpacings*(code : LONGINT; VAR glyphSpacings : WMGraphics.GlyphSpacings);
  76. BEGIN
  77. MapChars(code);
  78. IF (code >= 0) & (code < 256) & (glyphs[code].available) (* & (glyphs[code].img # NIL) *) THEN
  79. glyphSpacings.width := glyphs[code].w;
  80. glyphSpacings.ascent := ascent; glyphSpacings.descent := descent;
  81. glyphSpacings.bearing.l := glyphs[code].x;
  82. glyphSpacings.bearing.r := glyphs[code].dx - (glyphs[code].w + glyphs[code].x);
  83. glyphSpacings.height := glyphs[code].h;
  84. glyphSpacings.dy := ascent - glyphs[code].h - glyphs[code].y
  85. ELSE glyphSpacings.width := 5; glyphSpacings.height := 15; glyphSpacings.ascent := 16;
  86. END
  87. END GetGlyphSpacings;
  88. END Font;
  89. VAR
  90. bit: ARRAY 100H, 8 OF BOOLEAN; (* Bit[b, i] means bit i in byte b is set *)
  91. PROCEDURE LoadFont*(name : ARRAY OF CHAR) : Font;
  92. VAR r : Files.Reader; f : Files.File;
  93. BEGIN
  94. f := Files.Old(name);
  95. IF f = NIL THEN RETURN NIL END;
  96. Files.OpenReader(r, f, 0);
  97. RETURN StreamLoad(r)
  98. END LoadFont;
  99. PROCEDURE StreamLoad(r : Streams.Reader) : Font;
  100. VAR
  101. font : Font;
  102. ch : CHAR;
  103. minY, maxY, t, rbeg, rend : INTEGER;
  104. nofGlyphs, i, j, run, bits, b, pos, xw : LONGINT;
  105. p1 : Raster.Pixel;
  106. mode : Raster.Mode;
  107. mem: POINTER TO ARRAY OF CHAR;
  108. img: WMGraphics.Image;
  109. w,h: LONGINT;
  110. adr: ADDRESS;
  111. CONST
  112. MemoryOptimization = TRUE;
  113. BEGIN
  114. Raster.SetRGBA(p1, 255, 0, 0, 255);
  115. Raster.InitMode(mode, Raster.srcCopy);
  116. NEW(font);
  117. r.Char(font.idch); (* id *)
  118. r.Char(font.typech); (* metric or font *)
  119. r.Char(font.famch); (* family *)
  120. r.Char(font.varch); (* variant *)
  121. r.RawInt(font.height);
  122. r.RawInt(font.minX);
  123. r.RawInt(font.maxX);
  124. r.RawInt(minY); font.descent := -minY;
  125. r.RawInt(maxY); font.ascent := maxY;
  126. r.RawInt(font.nofRuns);
  127. IF TraceImport THEN
  128. KernelLog.String("id :"); KernelLog.Int(ORD(font.idch), 4); KernelLog.Ln;
  129. KernelLog.String("type :"); KernelLog.Int(ORD(font.typech), 4); KernelLog.Ln;
  130. KernelLog.String("family :"); KernelLog.Int(ORD(font.famch), 4); KernelLog.Ln;
  131. KernelLog.String("variant :"); KernelLog.Int(ORD(font.varch), 4); KernelLog.Ln;
  132. KernelLog.String("height :"); KernelLog.Int(font.height, 4); KernelLog.Ln;
  133. KernelLog.String("minX :"); KernelLog.Int(font.minX, 4); KernelLog.Ln;
  134. KernelLog.String("maxX :"); KernelLog.Int(font.ascent, 4); KernelLog.Ln;
  135. KernelLog.String("minY :"); KernelLog.Int(minY, 4); KernelLog.Ln;
  136. KernelLog.String("maxY :"); KernelLog.Int(font.maxY, 4); KernelLog.Ln;
  137. KernelLog.String("nofRuns :"); KernelLog.Int(font.nofRuns, 4); KernelLog.Ln;
  138. END;
  139. nofGlyphs := 0; i := 0;
  140. WHILE i < font.nofRuns DO
  141. r.RawInt(rbeg); font.runs[i].beg := rbeg;
  142. r.RawInt(rend); font.runs[i].end := rend;
  143. nofGlyphs := nofGlyphs + rend - rbeg;
  144. INC(i)
  145. END;
  146. run := 0;
  147. i := font.runs[run].beg;
  148. FOR j := 0 TO nofGlyphs - 1 DO
  149. r.RawInt(t); font.glyphs[i].dx := t;
  150. r.RawInt(t); font.glyphs[i].x := t;
  151. r.RawInt(t); font.glyphs[i].y := t;
  152. r.RawInt(t); font.glyphs[i].w := t;
  153. r.RawInt(t); font.glyphs[i].h := t;
  154. font.glyphs[i].available := TRUE;
  155. INC(i);
  156. IF i >= font.runs[run].end THEN INC(run); i := font.runs[run].beg END
  157. END;
  158. IF MemoryOptimization THEN
  159. w := 0; h := 0;
  160. FOR i := 0 TO 255 DO
  161. IF font.glyphs[i].available THEN
  162. INC(w, ((font.glyphs[i].w + 7) DIV 8) * 8);
  163. h := MAX(h, font.glyphs[i].h);
  164. END;
  165. END;
  166. NEW(img);
  167. Raster.Create(img, w, h, Raster.A1);
  168. mem := img.mem;
  169. adr := img.adr;
  170. END;
  171. FOR i := 0 TO 255 DO
  172. IF font.glyphs[i].available THEN
  173. xw := ((font.glyphs[i].w + 7) DIV 8) * 8;
  174. j := xw * font.glyphs[i].h DIV 8;
  175. IF xw * font.glyphs[i].h > 0 THEN
  176. NEW(font.glyphs[i].img);
  177. IF MemoryOptimization THEN
  178. Raster.CreateWithBuffer(font.glyphs[i].img, xw, font.glyphs[i].h, Raster.A1, mem, adr);
  179. ELSE
  180. Raster.Create(font.glyphs[i].img, xw, font.glyphs[i].h, Raster.A1);
  181. END;
  182. pos := 0;
  183. WHILE j > 0 DO
  184. r.Char(ch); bits := ORD(ch); DEC(j);
  185. FOR b := 0 TO 7 DO
  186. IF bit[ORD(ch), b] THEN
  187. IF pos MOD xw < font.glyphs[i].w THEN
  188. Raster.Put(font.glyphs[i].img, pos MOD xw, font.glyphs[i].h - pos DIV xw - 1, p1, mode);
  189. END
  190. ELSE
  191. END;
  192. INC(pos)
  193. END
  194. END
  195. END
  196. END
  197. END;
  198. RETURN font
  199. END StreamLoad;
  200. PROCEDURE StoreFont*(name : ARRAY OF CHAR; font : Font);
  201. VAR w : Files.Writer; f : Files.File;
  202. BEGIN
  203. f := Files.New(name);
  204. IF f = NIL THEN RETURN END;
  205. Files.OpenWriter(w, f, 0);
  206. StreamStore(w, font);
  207. w.Update;
  208. Files.Register(f)
  209. END StoreFont;
  210. PROCEDURE StreamStore(w : Streams.Writer; font : Font);
  211. VAR
  212. nofGlyphs, i, j, run, bits, b, pos, xw : LONGINT;
  213. p1 : Raster.Pixel;
  214. mode : Raster.Mode;
  215. BEGIN
  216. Raster.InitMode(mode, Raster.srcCopy);
  217. w.Char(font.idch); (* id *)
  218. w.Char(font.typech); (* metric or font *)
  219. w.Char(font.famch); (* family *)
  220. w.Char(font.varch); (* variant *)
  221. w.RawInt(font.height);
  222. w.RawInt(font.minX);
  223. w.RawInt(font.maxX);
  224. w.RawInt(-SHORT(font.descent));
  225. w.RawInt(SHORT(font.ascent));
  226. w.RawInt(font.nofRuns);
  227. nofGlyphs := 0; i := 0;
  228. WHILE i < font.nofRuns DO
  229. w.RawInt(SHORT(font.runs[i].beg));
  230. w.RawInt(SHORT(font.runs[i].end));
  231. nofGlyphs := nofGlyphs + font.runs[i].end - font.runs[i].beg;
  232. INC(i)
  233. END;
  234. run := 0;
  235. i := font.runs[run].beg;
  236. FOR j := 0 TO nofGlyphs - 1 DO
  237. w.RawInt(SHORT(font.glyphs[i].dx));
  238. w.RawInt(SHORT(font.glyphs[i].x));
  239. w.RawInt(SHORT(font.glyphs[i].y));
  240. w.RawInt(SHORT(font.glyphs[i].w));
  241. w.RawInt(SHORT(font.glyphs[i].h));
  242. INC(i);
  243. IF i >= font.runs[run].end THEN INC(run); i := font.runs[run].beg END
  244. END;
  245. FOR i := 0 TO 255 DO
  246. IF font.glyphs[i].available THEN
  247. xw := ((font.glyphs[i].w + 7) DIV 8) * 8;
  248. j := xw * font.glyphs[i].h DIV 8;
  249. IF xw * font.glyphs[i].h > 0 THEN
  250. pos := 0;
  251. WHILE j > 0 DO
  252. DEC(j);
  253. bits := 0;
  254. FOR b := 0 TO 7 DO
  255. Raster.Get(font.glyphs[i].img, pos MOD xw, font.glyphs[i].h - pos DIV xw - 1, p1, mode);
  256. IF p1[Raster.a] # 0X THEN INC(bits, 256) END;
  257. bits := bits DIV 2;
  258. INC(pos)
  259. END;
  260. w.Char(CHR(bits))
  261. END
  262. END
  263. END
  264. END
  265. END StreamStore;
  266. PROCEDURE InitBitTable;
  267. VAR b, i: LONGINT;
  268. BEGIN
  269. FOR b := 0 TO 0FFH DO
  270. FOR i := 0 TO 7 DO
  271. bit[b, i] := ODD(ASH(b, -i))
  272. END
  273. END
  274. END InitBitTable;
  275. PROCEDURE LoadExactFont*(fi : WMFontManager.FontInfo) : WMGraphics.Font;
  276. VAR exactName : ARRAY 256 OF CHAR;
  277. str : ARRAY 16 OF CHAR; f : WMGraphics.Font;
  278. BEGIN
  279. COPY(fi.name^, exactName);
  280. Strings.IntToStr(fi.size, str); Strings.Append(exactName, str);
  281. IF WMGraphics.FontBold IN fi.style THEN Strings.Append(exactName, "b") END;
  282. IF WMGraphics.FontItalic IN fi.style THEN Strings.Append(exactName, "i") END;
  283. Strings.Append(exactName, ".Scn.Fnt");
  284. f := LoadFont(exactName);
  285. IF f # NIL THEN
  286. COPY(fi.name^, f.name);
  287. f.size := fi.size;
  288. f.style := fi.style;
  289. END;
  290. RETURN f
  291. END LoadExactFont;
  292. PROCEDURE LoadApproximateFont*(fi : WMFontManager.FontInfo) : WMGraphics.Font;
  293. VAR exactName : ARRAY 256 OF CHAR;
  294. str : ARRAY 16 OF CHAR; f : WMGraphics.Font;
  295. BEGIN
  296. COPY(fi.name^, exactName);
  297. Strings.IntToStr(fi.size, str); Strings.Append(exactName, str);
  298. Strings.Append(exactName, ".Scn.Fnt");
  299. f := LoadFont(exactName);
  300. IF f # NIL THEN
  301. f.size := fi.size;
  302. f.style := fi.style
  303. END;
  304. RETURN f
  305. END LoadApproximateFont;
  306. BEGIN
  307. InitBitTable
  308. END WMOberonFonts.
  309. System.Free WMOberonFonts~