1
0

shapes.inc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. /*
  2. Legal:
  3. Version: MPL 1.1
  4. The contents of this file are subject to the Mozilla Public License Version
  5. 1.1 the "License"; you may not use this file except in compliance with
  6. the License. You may obtain a copy of the License at
  7. http://www.mozilla.org/MPL/
  8. Software distributed under the License is distributed on an "AS IS" basis,
  9. WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  10. for the specific language governing rights and limitations under the
  11. License.
  12. The Original Code is the YSI framework.
  13. The Initial Developer of the Original Code is Alex "Y_Less" Cole.
  14. Portions created by the Initial Developer are Copyright C 2011
  15. the Initial Developer. All Rights Reserved.
  16. Contributors:
  17. Y_Less
  18. koolk
  19. JoeBullet/Google63
  20. g_aSlice/Slice
  21. Misiur
  22. samphunter
  23. tianmeta
  24. maddinat0r
  25. spacemud
  26. Crayder
  27. Dayvison
  28. Ahmad45123
  29. Zeex
  30. irinel1996
  31. Yiin-
  32. Chaprnks
  33. Konstantinos
  34. Masterchen09
  35. Southclaws
  36. PatchwerkQWER
  37. m0k1
  38. paulommu
  39. udan111
  40. Thanks:
  41. JoeBullet/Google63 - Handy arbitrary ASM jump code using SCTRL.
  42. ZeeX - Very productive conversations.
  43. koolk - IsPlayerinAreaEx code.
  44. TheAlpha - Danish translation.
  45. breadfish - German translation.
  46. Fireburn - Dutch translation.
  47. yom - French translation.
  48. 50p - Polish translation.
  49. Zamaroht - Spanish translation.
  50. Los - Portuguese translation.
  51. Dracoblue, sintax, mabako, Xtreme, other coders - Producing other modes for
  52. me to strive to better.
  53. Pixels^ - Running XScripters where the idea was born.
  54. Matite - Pestering me to release it and using it.
  55. Very special thanks to:
  56. Thiadmer - PAWN, whose limits continue to amaze me!
  57. Kye/Kalcor - SA:MP.
  58. SA:MP Team past, present and future - SA:MP.
  59. Optional plugins:
  60. Gamer_Z - GPS.
  61. Incognito - Streamer.
  62. Me - sscanf2, fixes2, Whirlpool.
  63. */
  64. /*-------------------------------------------------------------------------*//**
  65. * <param name="ctx">The bitmap to modify.</param>
  66. * <param name="minX">The left of the array.</param>
  67. * <param name="minY">The top of the array.</param>
  68. * <param name="maxX">The right of the array.</param>
  69. * <param name="maxY">The bottom of the array.</param>
  70. * <param name="fillColour">The colour of the inside of the rectangle.</param>
  71. * <param name="lineColour">The colour of the rectangle border.</param>
  72. * <param name="linePattern[] = \"SOLID\"">How to draw the inside.</param>
  73. * <param name="fillPattern[] = \"SOLID\"">How to draw the border.</param>
  74. * <remarks>
  75. * This function draws a rectangle between two given co-ordinates. It can also
  76. * draw a border around the rectangle OUTSIDE the specified area of the
  77. * rectangle. If you want the border within the area specified you need to use
  78. * a smaller area.
  79. * </remarks>
  80. *//*------------------------------------------------------------------------**/
  81. // End the input above because all this code is being written with no testing
  82. // or compiling until I am home again. So in the interests of leaving the code
  83. // stable, this is all ignored.
  84. stock Bitmap_DrawRectangle(Bitmap:ctx, const minX, const minY, const maxX, const maxY, fillColour, lineColour = 0, linePattern[] = "SOLID", fillPattern[] = "SOLID")
  85. {
  86. if (fillColour)
  87. {
  88. _Bitmap_DoRectangle(ctx, minX, minY, maxX, maxY, fillColour, fillPattern);
  89. }
  90. if (lineColour)
  91. {
  92. // Do the borders.
  93. if (strcmp(linePattern, "DOTTED", true, 6))
  94. {
  95. new
  96. border = _Bitmap_Param(linePattern, "border");
  97. if (border == cellmin) border = 8;
  98. //printf("border = %d", border);
  99. //printf("1");
  100. _Bitmap_DoRectangle(ctx, minX - border, minY - border, maxX + border, minY, lineColour, linePattern),
  101. //printf("1");
  102. _Bitmap_DoRectangle(ctx, minX - border, minY, minX, maxY, lineColour, linePattern),
  103. //printf("1");
  104. _Bitmap_DoRectangle(ctx, minX - border, maxY, maxX + border, maxY + border, lineColour, linePattern),
  105. //printf("1");
  106. _Bitmap_DoRectangle(ctx, maxX, minY, maxX + border, maxY, lineColour, linePattern);
  107. //printf("1");
  108. }
  109. else
  110. {
  111. new
  112. border = _Bitmap_Param(linePattern, "border"),
  113. pat[128] = "STRIPED";
  114. strcat(pat, linePattern[6]);
  115. if (border == cellmin) border = 8;
  116. _Bitmap_DoRectangle(ctx, minX - border, minY - border, maxX + border, minY, lineColour, pat),
  117. _Bitmap_DoRectangle(ctx, minX - border, maxY, maxX + border, maxY + border, lineColour, pat),
  118. strcat(pat, ",HORIZONTAL"),
  119. _Bitmap_DoRectangle(ctx, minX - border, minY, minX, maxY, lineColour, pat),
  120. _Bitmap_DoRectangle(ctx, maxX, minY, maxX + border, maxY, lineColour, pat);
  121. }
  122. }
  123. }
  124. static stock _Bitmap_DoRectangle(Bitmap:ctx, minX, minY, maxX, maxY, colour, pattern[])
  125. {
  126. new
  127. width = Bitmap_Width(ctx);
  128. minY = max(0, minY),
  129. maxY = min(maxY, Bitmap_Height(ctx)),
  130. minX = max(0, minX),
  131. maxX = min(maxX, width),
  132. _Bitmap_MakePattern(pattern, minX, minY, 0, 0);
  133. new
  134. ya,
  135. read,
  136. a = (colour & 0xFF) + 1,
  137. na,
  138. suba,
  139. r = ((colour & 0xFF000000) >>> 16),
  140. g = ((colour & 0x00FF0000) >>> 16),
  141. b = ((colour & 0x0000FF00) >>> 8),
  142. orig;
  143. for (new y = minY; y != maxY; ++y)
  144. {
  145. read = Bitmap_IndexInt(ctx, minX, width, y),
  146. ya = y % YSI_gBitmapAlphaY;
  147. for (new x = minX; x != maxX; ++x)
  148. {
  149. suba = YSI_gBitmapAlpha[ya]{x % YSI_gBitmapAlphaX} * a;
  150. if (suba == 0xFF00)
  151. {
  152. YSI_gMallocMemory[read] = colour;
  153. }
  154. else if (suba >= 256)
  155. {
  156. // This is where we compensate for the odd shifts.
  157. na = 0xFF00 - suba,
  158. // Want this pixel in the final image.
  159. orig = YSI_gMallocMemory[read],
  160. YSI_gMallocMemory[read] = 0xFF |
  161. ((((orig & 0xFF000000) >>> 16) * na + r * suba) & 0xFF000000) |
  162. ((((orig & 0x00FF0000) >>> 16) * na + g * suba) & 0x00FF0000) |
  163. (((((orig & 0x0000FF00) >>> 8) * na + b * suba) & 0x00FF0000) >>> 8) ;
  164. }
  165. ++read;
  166. }
  167. }
  168. }
  169. static stock _Bitmap_RectangleRecopy(n, BitArray:pattern<PATTERN_MASK_X>)
  170. {
  171. for (new y = 1; y != n; ++y)
  172. {
  173. YSI_gBitmapAlpha[y] = pattern;
  174. }
  175. }
  176. /*-------------------------------------------------------------------------*//**
  177. * <param name="ctx">The bitmap to modify.</param>
  178. * <param name="x">The x co-ordinate of the circle centre.</param>
  179. * <param name="y">The y co-ordinate of the circle centre.</param>
  180. * <param name="radius">The size of the circle.</param>
  181. * <param name="fillColour">The colour of the inside of the circle.</param>
  182. * <param name="lineColour">The colour of the circle border.</param>
  183. * <param name="linePattern[] = \"SOLID\"">How to draw the inside.</param>
  184. * <param name="fillPattern[] = \"SOLID\"">How to draw the border.</param>
  185. * <remarks>
  186. * This function draws a circle centered on the given co-ordinates with the
  187. * given FLOAT radius, not an integer size because of diagonals. It can also
  188. * draw a border around the circle OUTSIDE the specified area of the circle.
  189. * If you want the border within the area specified you need to use a smaller
  190. * area.
  191. * </remarks>
  192. *//*------------------------------------------------------------------------**/
  193. stock Bitmap_DrawCircle(Bitmap:ctx, const x, const y, const Float:radius, fillColour, lineColour = 0, linePattern[] = "SOLID", fillPattern[] = "SOLID")
  194. {
  195. P:3("Bitmap_DrawCircle called: %d, %d, %d, %.2f, 0x%04x%04x, 0x%04x%04x, \"%s\", \"%s\"", _:ctx, x, y, radius, fillColour >>> 16, fillColour & 0xFFFF, lineColour >>> 16, lineColour & 0xFFFF, linePattern, fillPattern);
  196. Bitmap_DrawRing(ctx, x, y, 0.0, radius, fillColour, fillPattern);
  197. }
  198. /*-------------------------------------------------------------------------*//**
  199. * <param name="ctx">The bitmap to modify.</param>
  200. * <param name="x">The x co-ordinate of the ring centre.</param>
  201. * <param name="y">The y co-ordinate of the ring centre.</param>
  202. * <param name="inner">The inner size of the ring.</param>
  203. * <param name="outer">The outer size of the ring.</param>
  204. * <param name="colour">The colour of the ring.</param>
  205. * <param name="pattern[] = \"SOLID\"">How to draw the inside.</param>
  206. * <remarks>
  207. * This function draws a ring centered on the given co-ordinates with the
  208. * given FLOAT radius, not an integer size because of diagonals. This does not
  209. * draw a border as it is used for borders, and a border on a ring is ambiguous
  210. * - do you have it on the inside or not? Better to let the user decide.
  211. * </remarks>
  212. *//*------------------------------------------------------------------------**/
  213. stock Bitmap_DrawRing(Bitmap:ctx, x, y, Float:inner, Float:outer, colour, pattern[] = "SOLID")
  214. {
  215. P:3("Bitmap_DrawRing called: %d, %d, %d, %.2f, %.2f, 0x%04x%04x, \"%s\"", _:ctx, x, y, inner, outer, colour >>> 16, colour & 0xFFFF, pattern);
  216. new
  217. rad = max(floatround(outer, floatround_ceil), 0);
  218. if (rad == 0) return;
  219. new
  220. width = Bitmap_Width(ctx),
  221. // Get the circle bounds.
  222. minY = max(0, y - rad),
  223. maxY = min(y + rad + 1, Bitmap_Height(ctx)),
  224. minX = max(0, x - rad),
  225. maxX = min(x + rad + 1, width),
  226. // Get the approximate edges of the circle so we know how much blending
  227. // to use on the outer pixels.
  228. Float:outerMax = outer + 1.0,
  229. Float:rootMax = outer - 1.0,
  230. Float:outerMin = rootMax * rootMax,
  231. Float:innerMax = inner + 1.0,
  232. Float:rootMin = inner - 1.0,
  233. Float:innerMin;
  234. outerMax *= outerMax,
  235. innerMax *= innerMax;
  236. if (inner <= 0.0)
  237. {
  238. inner = 0.0;
  239. //innerMin = 0.0;
  240. }
  241. else innerMin = rootMin * rootMin;
  242. //new
  243. // Float:outerDiff = outerMax - outerMin,
  244. // Float:innerDiff = innerMax - innerMin;
  245. _Bitmap_MakePattern(pattern, minX, minY, 0, 0);
  246. new
  247. ya,
  248. // Get the float co-ordinates for ease of calculation.
  249. Float:fX = float(-rad), // Converted back from the integer version to.
  250. Float:fXX,
  251. Float:fY = float(-rad), // Make up for rounding errors.
  252. Float:fYY,
  253. Float:pos,
  254. read,
  255. a = (colour & 0xFF) + 1,
  256. na,
  257. suba,
  258. r = ((colour & 0xFF000000) >>> 16),
  259. g = ((colour & 0x00FF0000) >>> 16),
  260. b = ((colour & 0x0000FF00) >>> 8),
  261. orig;
  262. P:5("Bitmap_DrawRing: minX = %d, minY = %d, width = %d, height = %d", minX, minY, width, Bitmap_Height(ctx));
  263. for (y = minY; y != maxY; ++y, ++fY)
  264. {
  265. // "y" portion of the radius calculation.
  266. fYY = fY * fY,
  267. read = Bitmap_IndexInt(ctx, minX, width, y),
  268. ya = y % YSI_gBitmapAlphaY;
  269. P:6("Bitmap_DrawRing: 4: %.2f, %d, %d", fYY, read, ya);
  270. fXX = fX;
  271. for (x = minX; x != maxX; ++x, ++fXX, ++read)
  272. {
  273. pos = fXX * fXX + fYY;
  274. P:7("Bitmap_DrawRing: 5: %.2f <= %.2f <= %.2f", outerMin, pos, outerMax);
  275. // Slightly redundant check if "inner" is 0.0, but in that case will
  276. // at least never fail!
  277. if (pos >= innerMin)
  278. {
  279. // Calculate the full colour.
  280. suba = YSI_gBitmapAlpha[ya]{x % YSI_gBitmapAlphaX} * a;
  281. if (inner != 0.0 && pos <= innerMax)
  282. {
  283. // Draw partially (blending for the ring inner edge).
  284. //YSI_gMallocMemory[read] = 0xFF; // Black for now.
  285. suba = floatround((floatsqroot(pos) - rootMin) / 2.0 * float(suba));
  286. }
  287. else if (pos <= outerMin)
  288. {
  289. // Draw fully (part of the ring).
  290. //YSI_gMallocMemory[read] = suba;
  291. // Do nothing, but also don't end.
  292. }
  293. else if (pos <= outerMax)
  294. {
  295. // Draw partially (blending for the ring outer edge).
  296. //YSI_gMallocMemory[read] = 0xFF; // Black for now.
  297. suba = floatround((1.0 - (floatsqroot(pos) - rootMax) / 2.0) * float(suba));
  298. }
  299. else
  300. {
  301. // Otherwise don't draw anything at all - we are outside the ring.
  302. continue;
  303. }
  304. if (suba >= 0xFF00)
  305. {
  306. YSI_gMallocMemory[read] = colour;
  307. }
  308. else if (suba > 0xFF)
  309. {
  310. // This is where we compensate for the odd shifts.
  311. na = 0xFF00 - suba,
  312. // Want this pixel in the final image.
  313. orig = YSI_gMallocMemory[read],
  314. YSI_gMallocMemory[read] = 0xFF |
  315. ((((orig & 0xFF000000) >>> 16) * na + r * suba) & 0xFF000000) |
  316. ((((orig & 0x00FF0000) >>> 16) * na + g * suba) & 0x00FF0000) |
  317. (((((orig & 0x0000FF00) >>> 8) * na + b * suba) & 0x00FF0000) >>> 8) ;
  318. }
  319. }
  320. }
  321. }
  322. }