AGfxBuffer.Mod 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. (* ETH Oberon, Copyright 2001 ETH Zuerich Institut fuer Computersysteme, ETH Zentrum, CH-8092 Zuerich.
  2. Refer to the "General ETH Oberon System Source License" contract available at: http://www.oberon.ethz.ch/ *)
  3. MODULE GfxBuffer; (** portable *) (* eos *)
  4. (** AUTHOR "eos"; PURPOSE "Raster contexts rendering into background buffers"; *)
  5. (*
  6. 10.12.98 - first version; derived from GfxDev
  7. 25.8.99 - replaced GfxMaps with Images/GfxImages
  8. 10.8.99 - scratched SetPoint, added Close method
  9. 13.02.2000 - new get/set clip methods
  10. 10.05.2000 - Rect now ignores empty rectangles
  11. *)
  12. IMPORT
  13. Images := Raster, GfxMatrix, GfxImages, GfxRegions, Gfx, GfxRaster;
  14. TYPE
  15. Context* = OBJECT(GfxRaster.Context)
  16. VAR
  17. orgX*, orgY*: REAL; (** origin of default coordinate system **)
  18. scale*: REAL; (** default scale factor **)
  19. bgCol*: Gfx.Color; (** background color for erasing **)
  20. img*: Images.Image; (** target buffer **)
  21. pix: Images.Pixel;
  22. compOp:SHORTINT; (* composition operation for raster device *)
  23. (** initialize buffered context **)
  24. PROCEDURE InitBuffer* (img: Images.Image);
  25. BEGIN
  26. InitRaster();
  27. SELF.compOp := 1; (* Copy Op is default *)
  28. SELF.img := img;
  29. SELF.SetCoordinates(0, 0, 1);
  30. SELF.SetBGColor(Gfx.White);
  31. SELF.Reset();
  32. END InitBuffer;
  33. (*--- Methods ---*)
  34. (** current transformation matrix **)
  35. PROCEDURE ResetCTM*();
  36. BEGIN
  37. GfxMatrix.Translate(GfxMatrix.Identity, SELF.orgX, SELF.orgY, SELF.ctm);
  38. GfxMatrix.Scale(SELF.ctm, SELF.scale, SELF.scale, SELF.ctm)
  39. END ResetCTM;
  40. (** clipping **)
  41. PROCEDURE ResetClip*();
  42. BEGIN
  43. ResetClip^();
  44. SELF.clipReg.SetToRect(0, 0, SHORT(SELF.img.width), SHORT(SELF.img.height))
  45. END ResetClip;
  46. (** images and patterns **)
  47. PROCEDURE Image* (x, y: REAL; img: Images.Image; VAR filter: GfxImages.Filter);
  48. VAR m: GfxMatrix.Matrix; dx, dy, llx, lly, urx, ury: INTEGER; col: Images.Pixel;
  49. BEGIN
  50. GfxMatrix.Translate(SELF.ctm, x, y, m);
  51. dx := SHORT(ENTIER(m[2, 0] + 0.5));
  52. dy := SHORT(ENTIER(m[2, 1] + 0.5));
  53. col := filter.col;
  54. Images.SetModeColor(filter, SELF.fillCol.r, SELF.fillCol.g, SELF.fillCol.b);
  55. IF (filter.hshift # GfxImages.hshift) & (dx + 0.1 < m[2, 0]) & (m[2, 0] < dx + 0.9) OR
  56. (filter.vshift # GfxImages.vshift) & (dy + 0.1 < m[2, 1]) & (m[2, 1] < dy + 0.9) OR
  57. GfxMatrix.Scaled(m) OR
  58. GfxMatrix.Rotated(m)
  59. THEN
  60. GfxImages.Transform(img, SELF.img, m, filter)
  61. ELSE
  62. llx := 0; lly := 0; urx := SHORT(img.width); ury := SHORT(img.height);
  63. GfxRegions.ClipRect(llx, lly, urx, ury, SELF.clipReg.llx - dx, SELF.clipReg.lly - dy, SELF.clipReg.urx - dx, SELF.clipReg.ury - dy);
  64. IF SELF.clipReg.llx > dx THEN dx := SELF.clipReg.llx END;
  65. IF SELF.clipReg.lly > dy THEN dy := SELF.clipReg.lly END;
  66. IF dx + urx > SELF.img.width THEN urx := SHORT(SELF.img.width - dx) END;
  67. IF dy + ury > SELF.img.height THEN ury := SHORT(SELF.img.height - dy) END;
  68. IF dx < 0 THEN llx := -dx; dx := 0 END;
  69. IF dy < 0 THEN lly := -dy; dy := 0 END;
  70. IF (llx < urx) & (lly < ury) THEN
  71. IF ~GfxRegions.RectEmpty(llx, lly, urx, ury) THEN
  72. Images.Copy(img, SELF.img, llx, lly, urx, ury, dx, dy, filter)
  73. END
  74. END
  75. END;
  76. Images.SetModeColor(filter, ORD(col[Images.r]), ORD(col[Images.g]), ORD(col[Images.b]))
  77. END Image;
  78. PROCEDURE SetColPat* (col: Gfx.Color; pat: Gfx.Pattern);
  79. BEGIN
  80. SELF.col := col; SELF.pat := pat;
  81. Images.SetRGBA(SELF.pix, col.r, col.g, col.b, col.a)
  82. END SetColPat;
  83. PROCEDURE FillDot* (x, y: LONGINT);
  84. VAR px, py: LONGINT; mode: Images.Mode;
  85. BEGIN
  86. IF (SELF.clipState = GfxRaster.In) OR
  87. (SELF.clipState = GfxRaster.InOut) & SELF.clipReg.RectInside(SHORT(x), SHORT(y), SHORT(x+1), SHORT(y+1))
  88. THEN
  89. IF SELF.pat = NIL THEN
  90. Images.InitMode(mode, SELF.compOp);
  91. Images.Put(SELF.img, SHORT(x), SHORT(y), SELF.pix, mode)
  92. ELSE
  93. px := (x - ENTIER(SELF.orgX + SELF.pat.px + 0.5)) MOD SELF.pat.img.width;
  94. py := (y - ENTIER(SELF.orgY + SELF.pat.py + 0.5)) MOD SELF.pat.img.height;
  95. Images.InitModeColor(mode, Images.srcOverDst, SELF.col.r, SELF.col.g, SELF.col.b);
  96. Images.Copy(SELF.pat.img, SELF.img, px, py, px+1, py+1, SHORT(x), SHORT(y), mode)
  97. END
  98. END
  99. END FillDot;
  100. PROCEDURE FillRect* (llx, lly, urx, ury: LONGINT);
  101. VAR data: RegData; mode: Images.Mode;
  102. BEGIN
  103. IF (SELF.clipState # GfxRaster.Out) & (llx < urx) & (lly < ury) THEN
  104. IF SELF.pat = NIL THEN
  105. IF SELF.clipState = GfxRaster.In THEN
  106. Images.InitMode(mode, SELF.compOp);
  107. Images.Fill(SELF.img, SHORT(llx), SHORT(lly), SHORT(urx), SHORT(ury), SELF.pix, mode)
  108. ELSE
  109. data.bc := SELF;
  110. SELF.clipReg.Enumerate(SHORT(llx), SHORT(lly), SHORT(urx), SHORT(ury), Color, data)
  111. END
  112. ELSE
  113. data.bc := SELF;
  114. data.dx := SHORT(ENTIER(SELF.orgX + SELF.pat.px + 0.5));
  115. data.dy := SHORT(ENTIER(SELF.orgY + SELF.pat.py + 0.5));
  116. Images.InitModeColor(data.mode, Images.srcOverDst, SELF.col.r, SELF.col.g, SELF.col.b);
  117. SELF.clipReg.Enumerate(SHORT(llx), SHORT(lly), SHORT(urx), SHORT(ury), Tile, data)
  118. END
  119. END
  120. END FillRect;
  121. (*--- Exported Interface ---*)
  122. (** set default coordinate origin and scale factor **)
  123. PROCEDURE SetCoordinates* (x, y, scale: REAL);
  124. BEGIN
  125. SELF.orgX := x; SELF.orgY := y; SELF.scale := scale
  126. END SetCoordinates;
  127. (** set background color **)
  128. PROCEDURE SetBGColor* (col: Gfx.Color);
  129. BEGIN
  130. SELF.bgCol := col
  131. END SetBGColor;
  132. (** set composition operation as defined in Raster **)
  133. PROCEDURE SetCompOp* (op:SHORTINT);
  134. BEGIN
  135. SELF.compOp := op
  136. END SetCompOp;
  137. END Context;
  138. RegData = RECORD (GfxRegions.EnumData)
  139. dx, dy: INTEGER;
  140. bc: Context;
  141. mode: Images.Mode;
  142. END;
  143. (*--- Rendering ---*)
  144. PROCEDURE Color (llx, lly, urx, ury: INTEGER; VAR data: GfxRegions.EnumData);
  145. VAR bc: Context; mode: Images.Mode;
  146. BEGIN
  147. bc := data(RegData).bc;
  148. Images.InitMode(mode, bc.compOp);
  149. Images.Fill(bc.img, llx, lly, urx, ury, bc.pix, mode)
  150. END Color;
  151. PROCEDURE Tile (llx, lly, urx, ury: INTEGER; VAR data: GfxRegions.EnumData);
  152. VAR bc: Context;
  153. BEGIN
  154. WITH data: RegData DO
  155. bc := data.bc;
  156. Images.FillPattern(bc.pat.img, bc.img, llx, lly, urx, ury, data.dx, data.dy, data.mode)
  157. END
  158. END Tile;
  159. (*--- Exported Interface ---*)
  160. (** set default coordinate origin and scale factor **)
  161. PROCEDURE SetCoordinates* (bc: Context; x, y, scale: REAL);
  162. BEGIN
  163. bc.SetCoordinates (x, y, scale);
  164. END SetCoordinates;
  165. (** set background color **)
  166. PROCEDURE SetBGColor* (bc: Context; col: Gfx.Color);
  167. BEGIN
  168. bc.SetBGColor (col);
  169. END SetBGColor;
  170. (** set composition operation as defined in Raster **)
  171. PROCEDURE SetCompOp* (bc: Context; op:SHORTINT);
  172. BEGIN
  173. bc.SetCompOp (op);
  174. END SetCompOp;
  175. (** initialize buffered context **)
  176. PROCEDURE Init* (bc: Context; img: Images.Image);
  177. BEGIN
  178. bc.InitBuffer(img);
  179. END Init;
  180. END GfxBuffer.