From 788db64b8642bf31de6930d18a62177c64163ee0 Mon Sep 17 00:00:00 2001 From: Yuval Adam Date: Fri, 13 Mar 2015 12:24:02 +0200 Subject: Add grlib, fixes #5 --- grlib/circle.c | 564 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 564 insertions(+) create mode 100644 grlib/circle.c (limited to 'grlib/circle.c') diff --git a/grlib/circle.c b/grlib/circle.c new file mode 100644 index 0000000..a2d934f --- /dev/null +++ b/grlib/circle.c @@ -0,0 +1,564 @@ +//***************************************************************************** +// +// circle.c - Routines for drawing circles. +// +// Copyright (c) 2007-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Graphics Library. +// +//***************************************************************************** + +#include +#include +#include "driverlib/debug.h" +#include "grlib/grlib.h" + +//***************************************************************************** +// +//! \addtogroup primitives_api +//! @{ +// +//***************************************************************************** + +//***************************************************************************** +// +//! Draws a circle. +//! +//! \param pContext is a pointer to the drawing context to use. +//! \param i32X is the X coordinate of the center of the circle. +//! \param i32Y is the Y coordinate of the center of the circle. +//! \param i32Radius is the radius of the circle. +//! +//! This function draws a circle, utilizing the Bresenham circle drawing +//! algorithm. The extent of the circle is from \e i32X - \e i32Radius to +//! \e i32X + \e i32Radius and \e i32Y - \e i32Radius to \e i32Y + +//! \e i32Radius, inclusive. +//! +//! \return None. +// +//***************************************************************************** +void +GrCircleDraw(const tContext *pContext, int32_t i32X, int32_t i32Y, + int32_t i32Radius) +{ + int_fast32_t i32A, i32B, i32D, i32X1, i32Y1; + + // + // Check the arguments. + // + ASSERT(pContext); + + // + // Initialize the variables that control the Bresenham circle drawing + // algorithm. + // + i32A = 0; + i32B = i32Radius; + i32D = 3 - (2 * i32Radius); + + // + // Loop until the A delta is greater than the B delta, meaning that the + // entire circle has been drawn. + // + while(i32A <= i32B) + { + // + // Determine the row when subtracting the A delta. + // + i32Y1 = i32Y - i32A; + + // + // See if this row is within the clipping region. + // + if((i32Y1 >= pContext->sClipRegion.i16YMin) && + (i32Y1 <= pContext->sClipRegion.i16YMax)) + { + // + // Determine the column when subtracting the B delta. + // + i32X1 = i32X - i32B; + + // + // If this column is within the clipping region, then draw a pixel + // at that position. + // + if((i32X1 >= pContext->sClipRegion.i16XMin) && + (i32X1 <= pContext->sClipRegion.i16XMax)) + { + GrPixelDraw(pContext, i32X1, i32Y1); + } + + // + // Determine the column when adding the B delta. + // + i32X1 = i32X + i32B; + + // + // If this column is within the clipping region, then draw a pixel + // at that position. + // + if((i32X1 >= pContext->sClipRegion.i16XMin) && + (i32X1 <= pContext->sClipRegion.i16XMax)) + { + GrPixelDraw(pContext, i32X1, i32Y1); + } + } + + // + // Determine the row when adding the A delta. + // + i32Y1 = i32Y + i32A; + + // + // See if this row is within the clipping region, and the A delta is + // not zero (otherwise, it will be the same row as when the A delta was + // subtracted). + // + if((i32Y1 >= pContext->sClipRegion.i16YMin) && + (i32Y1 <= pContext->sClipRegion.i16YMax) && + (i32A != 0)) + { + // + // Determine the column when subtracting the B delta. + // + i32X1 = i32X - i32B; + + // + // If this column is within the clipping region, then draw a pixel + // at that position. + // + if((i32X1 >= pContext->sClipRegion.i16XMin) && + (i32X1 <= pContext->sClipRegion.i16XMax)) + { + GrPixelDraw(pContext, i32X1, i32Y1); + } + + // + // Determine the column when adding the B delta. + // + i32X1 = i32X + i32B; + + // + // If this column is within the clipping region, then draw a pixel + // at that position. + // + if((i32X1 >= pContext->sClipRegion.i16XMin) && + (i32X1 <= pContext->sClipRegion.i16XMax)) + { + GrPixelDraw(pContext, i32X1, i32Y1); + } + } + + // + // Only draw the complementary pixels if the A and B deltas are + // different (otherwise, they describe the same set of pixels). + // + if(i32A != i32B) + { + // + // Determine the row when subtracting the B delta. + // + i32Y1 = i32Y - i32B; + + // + // See if this row is within the clipping region. + // + if((i32Y1 >= pContext->sClipRegion.i16YMin) && + (i32Y1 <= pContext->sClipRegion.i16YMax)) + { + // + // Determine the column when subtracting the a delta. + // + i32X1 = i32X - i32A; + + // + // If this column is within the clipping region, then draw a + // pixel at that position. + // + if((i32X1 >= pContext->sClipRegion.i16XMin) && + (i32X1 <= pContext->sClipRegion.i16XMax)) + { + GrPixelDraw(pContext, i32X1, i32Y1); + } + + // + // Only draw the mirrored pixel if the A delta is non-zero + // (otherwise, it will be the same pixel). + // + if(i32A != 0) + { + // + // Determine the column when adding the A delta. + // + i32X1 = i32X + i32A; + + // + // If this column is within the clipping region, then draw + // a pixel at that position. + // + if((i32X1 >= pContext->sClipRegion.i16XMin) && + (i32X1 <= pContext->sClipRegion.i16XMax)) + { + GrPixelDraw(pContext, i32X1, i32Y1); + } + } + } + + // + // Determine the row when adding the B delta. + // + i32Y1 = i32Y + i32B; + + // + // See if this row is within the clipping region. + // + if((i32Y1 >= pContext->sClipRegion.i16YMin) && + (i32Y1 <= pContext->sClipRegion.i16YMax)) + { + // + // Determine the column when subtracting the A delta. + // + i32X1 = i32X - i32A; + + // + // If this column is within the clipping region, then draw a + // pixel at that position. + // + if((i32X1 >= pContext->sClipRegion.i16XMin) && + (i32X1 <= pContext->sClipRegion.i16XMax)) + { + GrPixelDraw(pContext, i32X1, i32Y1); + } + + // + // Only draw the mirrored pixel if the A delta is non-zero + // (otherwise, it will be the same pixel). + // + if(i32A != 0) + { + // + // Determine the column when adding the A delta. + // + i32X1 = i32X + i32A; + + // + // If this column is within the clipping region, then draw + // a pixel at that position. + // + if((i32X1 >= pContext->sClipRegion.i16XMin) && + (i32X1 <= pContext->sClipRegion.i16XMax)) + { + GrPixelDraw(pContext, i32X1, i32Y1); + } + } + } + } + + // + // See if the error term is negative. + // + if(i32D < 0) + { + // + // Since the error term is negative, adjust it based on a move in + // only the A delta. + // + i32D += (4 * i32A) + 6; + } + else + { + // + // Since the error term is non-negative, adjust it based on a move + // in both the A and B deltas. + // + i32D += (4 * (i32A - i32B)) + 10; + + // + // Decrement the B delta. + // + i32B -= 1; + } + + // + // Increment the A delta. + // + i32A++; + } +} + +//***************************************************************************** +// +//! Draws a filled circle. +//! +//! \param pContext is a pointer to the drawing context to use. +//! \param i32X is the X coordinate of the center of the circle. +//! \param i32Y is the Y coordinate of the center of the circle. +//! \param i32Radius is the radius of the circle. +//! +//! This function draws a filled circle, utilizing the Bresenham circle drawing +//! algorithm. The extent of the circle is from \e i32X - \e i32Radius to +//! \e i32X + \e i32Radius and \e i32Y - \e i32Radius to \e i32Y + +//! \e i32Radius, inclusive. +//! +//! \return None. +// +//***************************************************************************** +void +GrCircleFill(const tContext *pContext, int32_t i32X, int32_t i32Y, + int32_t i32Radius) +{ + int_fast32_t i32A, i32B, i32D, i32X1, i32X2, i32Y1; + + // + // Check the arguments. + // + ASSERT(pContext); + + // + // Initialize the variables that control the Bresenham circle drawing + // algorithm. + // + i32A = 0; + i32B = i32Radius; + i32D = 3 - (2 * i32Radius); + + // + // Loop until the A delta is greater than the B delta, meaning that the + // entire circle has been filled. + // + while(i32A <= i32B) + { + // + // Determine the row when subtracting the A delta. + // + i32Y1 = i32Y - i32A; + + // + // See if this row is within the clipping region. + // + if((i32Y1 >= pContext->sClipRegion.i16YMin) && + (i32Y1 <= pContext->sClipRegion.i16YMax)) + { + // + // Determine the column when subtracting the B delta, and move it + // to the left edge of the clipping region if it is to the left of + // the clipping region. + // + i32X1 = i32X - i32B; + if(i32X1 < pContext->sClipRegion.i16XMin) + { + i32X1 = pContext->sClipRegion.i16XMin; + } + + // + // Determine the column when adding the B delta, and move it to the + // right edge of the clipping region if it is to the right of the + // clipping region. + // + i32X2 = i32X + i32B; + if(i32X2 > pContext->sClipRegion.i16XMax) + { + i32X2 = pContext->sClipRegion.i16XMax; + } + + // + // Draw a horizontal line if this portion of the circle is within + // the clipping region. + // + if(i32X1 <= i32X2) + { + GrLineDrawH(pContext, i32X1, i32X2, i32Y1); + } + } + + // + // Determine the row when adding the A delta. + // + i32Y1 = i32Y + i32A; + + // + // See if this row is within the clipping region, and the A delta is + // not zero (otherwise, this describes the same row of the circle). + // + if((i32Y1 >= pContext->sClipRegion.i16YMin) && + (i32Y1 <= pContext->sClipRegion.i16YMax) && + (i32A != 0)) + { + // + // Determine the column when subtracting the B delta, and move it + // to the left edge of the clipping region if it is to the left of + // the clipping region. + // + i32X1 = i32X - i32B; + if(i32X1 < pContext->sClipRegion.i16XMin) + { + i32X1 = pContext->sClipRegion.i16XMin; + } + + // + // Determine the column when adding the B delta, and move it to the + // right edge of the clipping region if it is to the right of the + // clipping region. + // + i32X2 = i32X + i32B; + if(i32X2 > pContext->sClipRegion.i16XMax) + { + i32X2 = pContext->sClipRegion.i16XMax; + } + + // + // Draw a horizontal line if this portion of the circle is within + // the clipping region. + // + if(i32X1 <= i32X2) + { + GrLineDrawH(pContext, i32X1, i32X2, i32Y1); + } + } + + // + // Only draw the complementary lines if the B delta is about to change + // and the A and B delta are different (otherwise, they describe the + // same set of pixels). + // + if((i32D >= 0) && (i32A != i32B)) + { + // + // Determine the row when subtracting the B delta. + // + i32Y1 = i32Y - i32B; + + // + // See if this row is within the clipping region. + // + if((i32Y1 >= pContext->sClipRegion.i16YMin) && + (i32Y1 <= pContext->sClipRegion.i16YMax)) + { + // + // Determine the column when subtracting the A delta, and move + // it to the left edge of the clipping regino if it is to the + // left of the clipping region. + // + i32X1 = i32X - i32A; + if(i32X1 < pContext->sClipRegion.i16XMin) + { + i32X1 = pContext->sClipRegion.i16XMin; + } + + // + // Determine the column when adding the A delta, and move it to + // the right edge of the clipping region if it is to the right + // of the clipping region. + // + i32X2 = i32X + i32A; + if(i32X2 > pContext->sClipRegion.i16XMax) + { + i32X2 = pContext->sClipRegion.i16XMax; + } + + // + // Draw a horizontal line if this portion of the circle is + // within the clipping region. + // + if(i32X1 <= i32X2) + { + GrLineDrawH(pContext, i32X1, i32X2, i32Y1); + } + } + + // + // Determine the row when adding the B delta. + // + i32Y1 = i32Y + i32B; + + // + // See if this row is within the clipping region. + // + if((i32Y1 >= pContext->sClipRegion.i16YMin) && + (i32Y1 <= pContext->sClipRegion.i16YMax)) + { + // + // Determine the column when subtracting the A delta, and move + // it to the left edge of the clipping region if it is to the + // left of the clipping region. + // + i32X1 = i32X - i32A; + if(i32X1 < pContext->sClipRegion.i16XMin) + { + i32X1 = pContext->sClipRegion.i16XMin; + } + + // + // Determine the column when adding the A delta, and move it to + // the right edge of the clipping region if it is to the right + // of the clipping region. + // + i32X2 = i32X + i32A; + if(i32X2 > pContext->sClipRegion.i16XMax) + { + i32X2 = pContext->sClipRegion.i16XMax; + } + + // + // Draw a horizontal line if this portion of the circle is + // within the clipping region. + // + if(i32X1 <= i32X2) + { + GrLineDrawH(pContext, i32X1, i32X2, i32Y1); + } + } + } + + // + // See if the error term is negative. + // + if(i32D < 0) + { + // + // Since the error term is negative, adjust it based on a move in + // only the A delta. + // + i32D += (4 * i32A) + 6; + } + else + { + // + // Since the error term is non-negative, adjust it based on a move + // in both the A and B deltas. + // + i32D += (4 * (i32A - i32B)) + 10; + + // + // Decrement the B delta. + // + i32B -= 1; + } + + // + // Increment the A delta. + // + i32A++; + } +} + +//***************************************************************************** +// +// Close the Doxygen group. +//! @} +// +//***************************************************************************** -- cgit v1.3.1