You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

565 lines
18 KiB

5 years ago
  1. /* --COPYRIGHT--,BSD
  2. * Copyright (c) 2013, Texas Instruments Incorporated
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. *
  9. * * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. *
  12. * * Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * * Neither the name of Texas Instruments Incorporated nor the names of
  17. * its contributors may be used to endorse or promote products derived
  18. * from this software without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  21. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  22. * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  23. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  24. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  25. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  26. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  27. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  28. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  29. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  30. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. * --/COPYRIGHT--*/
  32. #include "grlib.h"
  33. //*****************************************************************************
  34. //
  35. //! \addtogroup circle_api
  36. //! @{
  37. //
  38. //*****************************************************************************
  39. //*****************************************************************************
  40. //
  41. //! Draws a circle.
  42. //!
  43. //! \param pContext is a pointer to the drawing context to use.
  44. //! \param lX is the X coordinate of the center of the circle.
  45. //! \param lY is the Y coordinate of the center of the circle.
  46. //! \param lRadius is the radius of the circle.
  47. //!
  48. //! This function draws a circle, utilizing the Bresenham circle drawing
  49. //! algorithm. The extent of the circle is from \e lX - \e lRadius to \e lX +
  50. //! \e lRadius and \e lY - \e lRadius to \e lY + \e lRadius, inclusive.
  51. //!
  52. //! \return None.
  53. //
  54. //*****************************************************************************
  55. void
  56. GrCircleDraw(const tContext *pContext, long lX, long lY, long lRadius)
  57. {
  58. long lA, lB, lD, lX1, lY1;
  59. //
  60. // Check the arguments.
  61. //
  62. assert(pContext);
  63. //
  64. // Initialize the variables that control the Bresenham circle drawing
  65. // algorithm.
  66. //
  67. lA = 0;
  68. lB = lRadius;
  69. lD = 3 - (2 * lRadius);
  70. //
  71. // Loop until the A delta is greater than the B delta, meaning that the
  72. // entire circle has been drawn.
  73. //
  74. while(lA <= lB)
  75. {
  76. //
  77. // Determine the row when subtracting the A delta.
  78. //
  79. lY1 = lY - lA;
  80. //
  81. // See if this row is within the clipping region.
  82. //
  83. if((lY1 >= pContext->sClipRegion.sYMin) &&
  84. (lY1 <= pContext->sClipRegion.sYMax))
  85. {
  86. //
  87. // Determine the column when subtracting the B delta.
  88. //
  89. lX1 = lX - lB;
  90. //
  91. // If this column is within the clipping region, then draw a pixel
  92. // at that position.
  93. //
  94. if((lX1 >= pContext->sClipRegion.sXMin) &&
  95. (lX1 <= pContext->sClipRegion.sXMax))
  96. {
  97. GrPixelDraw(pContext, lX1, lY1);
  98. }
  99. //
  100. // Determine the column when adding the B delta.
  101. //
  102. lX1 = lX + lB;
  103. //
  104. // If this column is within the clipping region, then draw a pixel
  105. // at that position.
  106. //
  107. if((lX1 >= pContext->sClipRegion.sXMin) &&
  108. (lX1 <= pContext->sClipRegion.sXMax))
  109. {
  110. GrPixelDraw(pContext, lX1, lY1);
  111. }
  112. }
  113. //
  114. // Determine the row when adding the A delta.
  115. //
  116. lY1 = lY + lA;
  117. //
  118. // See if this row is within the clipping region, and the A delta is
  119. // not zero (otherwise, it will be the same row as when the A delta was
  120. // subtracted).
  121. //
  122. if((lY1 >= pContext->sClipRegion.sYMin) &&
  123. (lY1 <= pContext->sClipRegion.sYMax) &&
  124. (lA != 0))
  125. {
  126. //
  127. // Determine the column when subtracting the B delta.
  128. //
  129. lX1 = lX - lB;
  130. //
  131. // If this column is within the clipping region, then draw a pixel
  132. // at that position.
  133. //
  134. if((lX1 >= pContext->sClipRegion.sXMin) &&
  135. (lX1 <= pContext->sClipRegion.sXMax))
  136. {
  137. GrPixelDraw(pContext, lX1, lY1);
  138. }
  139. //
  140. // Determine the column when adding the B delta.
  141. //
  142. lX1 = lX + lB;
  143. //
  144. // If this column is within the clipping region, then draw a pixel
  145. // at that position.
  146. //
  147. if((lX1 >= pContext->sClipRegion.sXMin) &&
  148. (lX1 <= pContext->sClipRegion.sXMax))
  149. {
  150. GrPixelDraw(pContext, lX1, lY1);
  151. }
  152. }
  153. //
  154. // Only draw the complementary pixels if the A and B deltas are
  155. // different (otherwise, they describe the same set of pixels).
  156. //
  157. if(lA != lB)
  158. {
  159. //
  160. // Determine the row when subtracting the B delta.
  161. //
  162. lY1 = lY - lB;
  163. //
  164. // See if this row is within the clipping region.
  165. //
  166. if((lY1 >= pContext->sClipRegion.sYMin) &&
  167. (lY1 <= pContext->sClipRegion.sYMax))
  168. {
  169. //
  170. // Determine the column when subtracting the a delta.
  171. //
  172. lX1 = lX - lA;
  173. //
  174. // If this column is within the clipping region, then draw a
  175. // pixel at that position.
  176. //
  177. if((lX1 >= pContext->sClipRegion.sXMin) &&
  178. (lX1 <= pContext->sClipRegion.sXMax))
  179. {
  180. GrPixelDraw(pContext, lX1, lY1);
  181. }
  182. //
  183. // Only draw the mirrored pixel if the A delta is non-zero
  184. // (otherwise, it will be the same pixel).
  185. //
  186. if(lA != 0)
  187. {
  188. //
  189. // Determine the column when adding the A delta.
  190. //
  191. lX1 = lX + lA;
  192. //
  193. // If this column is within the clipping region, then draw
  194. // a pixel at that position.
  195. //
  196. if((lX1 >= pContext->sClipRegion.sXMin) &&
  197. (lX1 <= pContext->sClipRegion.sXMax))
  198. {
  199. GrPixelDraw(pContext, lX1, lY1);
  200. }
  201. }
  202. }
  203. //
  204. // Determine the row when adding the B delta.
  205. //
  206. lY1 = lY + lB;
  207. //
  208. // See if this row is within the clipping region.
  209. //
  210. if((lY1 >= pContext->sClipRegion.sYMin) &&
  211. (lY1 <= pContext->sClipRegion.sYMax))
  212. {
  213. //
  214. // Determine the column when subtracting the A delta.
  215. //
  216. lX1 = lX - lA;
  217. //
  218. // If this column is within the clipping region, then draw a
  219. // pixel at that position.
  220. //
  221. if((lX1 >= pContext->sClipRegion.sXMin) &&
  222. (lX1 <= pContext->sClipRegion.sXMax))
  223. {
  224. GrPixelDraw(pContext, lX1, lY1);
  225. }
  226. //
  227. // Only draw the mirrored pixel if the A delta is non-zero
  228. // (otherwise, it will be the same pixel).
  229. //
  230. if(lA != 0)
  231. {
  232. //
  233. // Determine the column when adding the A delta.
  234. //
  235. lX1 = lX + lA;
  236. //
  237. // If this column is within the clipping region, then draw
  238. // a pixel at that position.
  239. //
  240. if((lX1 >= pContext->sClipRegion.sXMin) &&
  241. (lX1 <= pContext->sClipRegion.sXMax))
  242. {
  243. GrPixelDraw(pContext, lX1, lY1);
  244. }
  245. }
  246. }
  247. }
  248. //
  249. // See if the error term is negative.
  250. //
  251. if(lD < 0)
  252. {
  253. //
  254. // Since the error term is negative, adjust it based on a move in
  255. // only the A delta.
  256. //
  257. lD += (4 * lA) + 6;
  258. }
  259. else
  260. {
  261. //
  262. // Since the error term is non-negative, adjust it based on a move
  263. // in both the A and B deltas.
  264. //
  265. lD += (4 * (lA - lB)) + 10;
  266. //
  267. // Decrement the B delta.
  268. //
  269. lB -= 1;
  270. }
  271. //
  272. // Increment the A delta.
  273. //
  274. lA++;
  275. }
  276. }
  277. //*****************************************************************************
  278. //
  279. //! Draws a filled circle.
  280. //!
  281. //! \param pContext is a pointer to the drawing context to use.
  282. //! \param lX is the X coordinate of the center of the circle.
  283. //! \param lY is the Y coordinate of the center of the circle.
  284. //! \param lRadius is the radius of the circle.
  285. //!
  286. //! This function draws a filled circle, utilizing the Bresenham circle drawing
  287. //! algorithm. The extent of the circle is from \e lX - \e lRadius to \e lX +
  288. //! \e lRadius and \e lY - \e lRadius to \e lY + \e lRadius, inclusive.
  289. //!
  290. //! \return None.
  291. //
  292. //*****************************************************************************
  293. void
  294. GrCircleFill(const tContext *pContext, long lX, long lY, long lRadius)
  295. {
  296. long lA, lB, lD, lX1, lX2, lY1;
  297. //
  298. // Check the arguments.
  299. //
  300. assert(pContext);
  301. //
  302. // Initialize the variables that control the Bresenham circle drawing
  303. // algorithm.
  304. //
  305. lA = 0;
  306. lB = lRadius;
  307. lD = 3 - (2 * lRadius);
  308. //
  309. // Loop until the A delta is greater than the B delta, meaning that the
  310. // entire circle has been filled.
  311. //
  312. while(lA <= lB)
  313. {
  314. //
  315. // Determine the row when subtracting the A delta.
  316. //
  317. lY1 = lY - lA;
  318. //
  319. // See if this row is within the clipping region.
  320. //
  321. if((lY1 >= pContext->sClipRegion.sYMin) &&
  322. (lY1 <= pContext->sClipRegion.sYMax))
  323. {
  324. //
  325. // Determine the column when subtracting the B delta, and move it
  326. // to the left edge of the clipping region if it is to the left of
  327. // the clipping region.
  328. //
  329. lX1 = lX - lB;
  330. if(lX1 < pContext->sClipRegion.sXMin)
  331. {
  332. lX1 = pContext->sClipRegion.sXMin;
  333. }
  334. //
  335. // Determine the column when adding the B delta, and move it to the
  336. // right edge of the clipping region if it is to the right of the
  337. // clipping region.
  338. //
  339. lX2 = lX + lB;
  340. if(lX2 > pContext->sClipRegion.sXMax)
  341. {
  342. lX2 = pContext->sClipRegion.sXMax;
  343. }
  344. //
  345. // Draw a horizontal line if this portion of the circle is within
  346. // the clipping region.
  347. //
  348. if(lX1 <= lX2)
  349. {
  350. GrLineDrawH(pContext, lX1, lX2, lY1);
  351. }
  352. }
  353. //
  354. // Determine the row when adding the A delta.
  355. //
  356. lY1 = lY + lA;
  357. //
  358. // See if this row is within the clipping region, and the A delta is
  359. // not zero (otherwise, this describes the same row of the circle).
  360. //
  361. if((lY1 >= pContext->sClipRegion.sYMin) &&
  362. (lY1 <= pContext->sClipRegion.sYMax) &&
  363. (lA != 0))
  364. {
  365. //
  366. // Determine the column when subtracting the B delta, and move it
  367. // to the left edge of the clipping region if it is to the left of
  368. // the clipping region.
  369. //
  370. lX1 = lX - lB;
  371. if(lX1 < pContext->sClipRegion.sXMin)
  372. {
  373. lX1 = pContext->sClipRegion.sXMin;
  374. }
  375. //
  376. // Determine the column when adding the B delta, and move it to the
  377. // right edge of the clipping region if it is to the right of the
  378. // clipping region.
  379. //
  380. lX2 = lX + lB;
  381. if(lX2 > pContext->sClipRegion.sXMax)
  382. {
  383. lX2 = pContext->sClipRegion.sXMax;
  384. }
  385. //
  386. // Draw a horizontal line if this portion of the circle is within
  387. // the clipping region.
  388. //
  389. if(lX1 <= lX2)
  390. {
  391. GrLineDrawH(pContext, lX1, lX2, lY1);
  392. }
  393. }
  394. //
  395. // Only draw the complementary lines if the B delta is about to change
  396. // and the A and B delta are different (otherwise, they describe the
  397. // same set of pixels).
  398. //
  399. if((lD >= 0) && (lA != lB))
  400. {
  401. //
  402. // Determine the row when subtracting the B delta.
  403. //
  404. lY1 = lY - lB;
  405. //
  406. // See if this row is within the clipping region.
  407. //
  408. if((lY1 >= pContext->sClipRegion.sYMin) &&
  409. (lY1 <= pContext->sClipRegion.sYMax))
  410. {
  411. //
  412. // Determine the column when subtracting the A delta, and move
  413. // it to the left edge of the clipping regino if it is to the
  414. // left of the clipping region.
  415. //
  416. lX1 = lX - lA;
  417. if(lX1 < pContext->sClipRegion.sXMin)
  418. {
  419. lX1 = pContext->sClipRegion.sXMin;
  420. }
  421. //
  422. // Determine the column when adding the A delta, and move it to
  423. // the right edge of the clipping region if it is to the right
  424. // of the clipping region.
  425. //
  426. lX2 = lX + lA;
  427. if(lX2 > pContext->sClipRegion.sXMax)
  428. {
  429. lX2 = pContext->sClipRegion.sXMax;
  430. }
  431. //
  432. // Draw a horizontal line if this portion of the circle is
  433. // within the clipping region.
  434. //
  435. if(lX1 <= lX2)
  436. {
  437. GrLineDrawH(pContext, lX1, lX2, lY1);
  438. }
  439. }
  440. //
  441. // Determine the row when adding the B delta.
  442. //
  443. lY1 = lY + lB;
  444. //
  445. // See if this row is within the clipping region.
  446. //
  447. if((lY1 >= pContext->sClipRegion.sYMin) &&
  448. (lY1 <= pContext->sClipRegion.sYMax))
  449. {
  450. //
  451. // Determine the column when subtracting the A delta, and move
  452. // it to the left edge of the clipping region if it is to the
  453. // left of the clipping region.
  454. //
  455. lX1 = lX - lA;
  456. if(lX1 < pContext->sClipRegion.sXMin)
  457. {
  458. lX1 = pContext->sClipRegion.sXMin;
  459. }
  460. //
  461. // Determine the column when adding the A delta, and move it to
  462. // the right edge of the clipping region if it is to the right
  463. // of the clipping region.
  464. //
  465. lX2 = lX + lA;
  466. if(lX2 > pContext->sClipRegion.sXMax)
  467. {
  468. lX2 = pContext->sClipRegion.sXMax;
  469. }
  470. //
  471. // Draw a horizontal line if this portion of the circle is
  472. // within the clipping region.
  473. //
  474. if(lX1 <= lX2)
  475. {
  476. GrLineDrawH(pContext, lX1, lX2, lY1);
  477. }
  478. }
  479. }
  480. //
  481. // See if the error term is negative.
  482. //
  483. if(lD < 0)
  484. {
  485. //
  486. // Since the error term is negative, adjust it based on a move in
  487. // only the A delta.
  488. //
  489. lD += (4 * lA) + 6;
  490. }
  491. else
  492. {
  493. //
  494. // Since the error term is non-negative, adjust it based on a move
  495. // in both the A and B deltas.
  496. //
  497. lD += (4 * (lA - lB)) + 10;
  498. //
  499. // Decrement the B delta.
  500. //
  501. lB -= 1;
  502. }
  503. //
  504. // Increment the A delta.
  505. //
  506. lA++;
  507. }
  508. }
  509. //*****************************************************************************
  510. //
  511. // Close the Doxygen group.
  512. //! @}
  513. //
  514. //*****************************************************************************