static void onDraw(tContext *pContext) { // first draw the datetime uint8_t totalgrid = window_readconfig()->sports_grid + 3; GrContextForegroundSet(pContext, ClrWhite); switch(window_readconfig()->sports_grid) { case GRID_3: GrRectFill(pContext, ®ion_3grid[0]); GrLineDrawV(pContext, region_3grid[1].sXMax, region_3grid[1].sYMin, region_3grid[1].sYMax); break; case GRID_4: GrRectFill(pContext, ®ion_4grid[0]); GrLineDrawH(pContext, region_4grid[1].sXMin, region_4grid[1].sXMax, region_4grid[1].sYMax); GrLineDrawH(pContext, region_4grid[2].sXMin, region_4grid[2].sXMax, region_4grid[2].sYMax); break; case GRID_5: GrRectFill(pContext, ®ion_5grid[0]); GrLineDrawH(pContext, region_5grid[1].sXMin, region_5grid[2].sXMax, region_5grid[1].sYMax); GrLineDrawV(pContext, region_5grid[1].sXMax, region_5grid[1].sYMin, region_5grid[3].sYMax); break; } GrContextForegroundSet(pContext, ClrWhite); for(uint8_t g = 0; g < totalgrid; g++) { drawGridData(pContext, window_readconfig()->sports_grid_data[g] , grid_data[g]); } }
//***************************************************************************** // //! Draws a rectangle. //! //! \param pContext is a pointer to the drawing context to use. //! \param pRect is a pointer to the structure containing the extents of the //! rectangle. //! //! This function draws a rectangle. The rectangle will extend from \e i32XMin //! to \e i32XMax and \e i32YMin to \e i32YMax, inclusive. //! //! \return None. // //***************************************************************************** void GrRectDraw(const tContext *pContext, const tRectangle *pRect) { // // Check the arguments. // ASSERT(pContext); ASSERT(pRect); // // Draw a line across the top of the rectangle. // GrLineDrawH(pContext, pRect->i16XMin, pRect->i16XMax, pRect->i16YMin); // // Return if the rectangle is one pixel tall. // if(pRect->i16YMin == pRect->i16YMax) { return; } // // Draw a line down the right side of the rectangle. // GrLineDrawV(pContext, pRect->i16XMax, pRect->i16YMin + 1, pRect->i16YMax); // // Return if the rectangle is one pixel wide. // if(pRect->i16XMin == pRect->i16XMax) { return; } // // Draw a line across the bottom of the rectangle. // GrLineDrawH(pContext, pRect->i16XMax - 1, pRect->i16XMin, pRect->i16YMax); // // Return if the rectangle is two pixels tall. // if((pRect->i16YMin + 1) == pRect->i16YMax) { return; } // // Draw a line up the left side of the rectangle. // GrLineDrawV(pContext, pRect->i16XMin, pRect->i16YMax - 1, pRect->i16YMin + 1); }
//***************************************************************************** // // Handle keyboard updates. // //***************************************************************************** void HandleKeyboard(void) { // // Nothing to do if the keyboard is not active. // if(g_i32ScreenIdx != SCREEN_KEYBOARD) { return; } // // If the mid value is hit then clear the cursor. // if(g_ui32CursorDelay == KEYBOARD_BLINK_RATE / 2) { GrContextForegroundSet(&g_sContext, ClrBlack); // // Keep the counter moving now that the clearing has been handled. // g_ui32CursorDelay--; } else if(g_ui32CursorDelay == 0) { GrContextForegroundSet(&g_sContext, ClrWhite); // // Reset the blink delay now that the drawing of the cursor has been // handled. // g_ui32CursorDelay = KEYBOARD_BLINK_RATE; } else { return; } // // Draw the cursor only if it is time. // GrLineDrawV(&g_sContext, BG_MIN_X + g_i32StringWidth , BG_MIN_Y + 20, BG_MIN_Y + 40); }
//***************************************************************************** // //! Draws a line. //! //! \param pContext is a pointer to the drawing context to use. //! \param i32X1 is the X coordinate of the start of the line. //! \param i32Y1 is the Y coordinate of the start of the line. //! \param i32X2 is the X coordinate of the end of the line. //! \param i32Y2 is the Y coordinate of the end of the line. //! //! This function draws a line, utilizing GrLineDrawH() and GrLineDrawV() to //! draw the line as efficiently as possible. The line is clipped to the //! clippping rectangle using the Cohen-Sutherland clipping algorithm, and then //! scan converted using Bresenham's line drawing algorithm. //! //! \return None. // //***************************************************************************** void GrLineDraw(const tContext *pContext, int32_t i32X1, int32_t i32Y1, int32_t i32X2, int32_t i32Y2) { int32_t i32Error, i32DeltaX, i32DeltaY, i32YStep, bSteep; // // Check the arguments. // ASSERT(pContext); // // See if this is a vertical line. // if(i32X1 == i32X2) { // // It is more efficient to avoid Bresenham's algorithm when drawing a // vertical line, so use the vertical line routine to draw this line. // GrLineDrawV(pContext, i32X1, i32Y1, i32Y2); // // The line has ben drawn, so return. // return; } // // See if this is a horizontal line. // if(i32Y1 == i32Y2) { // // It is more efficient to avoid Bresenham's algorithm when drawing a // horizontal line, so use the horizontal line routien to draw this // line. // GrLineDrawH(pContext, i32X1, i32X2, i32Y1); // // The line has ben drawn, so return. // return; } // // Clip this line if necessary, and return without drawing anything if the // line does not cross the clipping region. // if(GrLineClip(pContext, &i32X1, &i32Y1, &i32X2, &i32Y2) == 0) { return; } // // Determine if the line is steep. A steep line has more motion in the Y // direction than the X direction. // if(((i32Y2 > i32Y1) ? (i32Y2 - i32Y1) : (i32Y1 - i32Y2)) > ((i32X2 > i32X1) ? (i32X2 - i32X1) : (i32X1 - i32X2))) { bSteep = 1; } else { bSteep = 0; } // // If the line is steep, then swap the X and Y coordinates. // if(bSteep) { i32Error = i32X1; i32X1 = i32Y1; i32Y1 = i32Error; i32Error = i32X2; i32X2 = i32Y2; i32Y2 = i32Error; } // // If the starting X coordinate is larger than the ending X coordinate, // then swap the start and end coordinates. // if(i32X1 > i32X2) { i32Error = i32X1; i32X1 = i32X2; i32X2 = i32Error; i32Error = i32Y1; i32Y1 = i32Y2; i32Y2 = i32Error; } // // Compute the difference between the start and end coordinates in each // axis. // i32DeltaX = i32X2 - i32X1; i32DeltaY = (i32Y2 > i32Y1) ? (i32Y2 - i32Y1) : (i32Y1 - i32Y2); // // Initialize the error term to negative half the X delta. // i32Error = -i32DeltaX / 2; // // Determine the direction to step in the Y axis when required. // if(i32Y1 < i32Y2) { i32YStep = 1; } else { i32YStep = -1; } // // Loop through all the points along the X axis of the line. // for(; i32X1 <= i32X2; i32X1++) { // // See if this is a steep line. // if(bSteep) { // // Plot this point of the line, swapping the X and Y coordinates. // DpyPixelDraw(pContext->psDisplay, i32Y1, i32X1, pContext->ui32Foreground); } else { // // Plot this point of the line, using the coordinates as is. // DpyPixelDraw(pContext->psDisplay, i32X1, i32Y1, pContext->ui32Foreground); } // // Increment the error term by the Y delta. // i32Error += i32DeltaY; // // See if the error term is now greater than zero. // if(i32Error > 0) { // // Take a step in the Y axis. // i32Y1 += i32YStep; // // Decrement the error term by the X delta. // i32Error -= i32DeltaX; } } }
//***************************************************************************** // //! Draws the strip chart into a drawing context, off-screen buffer. //! //! \param psChartWidget points at the StripsChartWidget being processed. //! \param psContext points to the context where all drawing should be done. //! //! This function renders a strip chart into a drawing context. //! It assumes that the drawing context is an off-screen buffer, and that //! the entire buffer belongs to this widget. //! //! \return None. // //***************************************************************************** void StripChartDraw(tStripChartWidget *psChartWidget, tContext *psContext) { tStripChartAxis *psAxisY; int32_t i32Y; int32_t i32Ygrid; int32_t i32X; int32_t i32GridRange; int32_t i32DispRange; int32_t i32GridMin; int32_t i32DispMax; tStripChartSeries *psSeries; // // Check the parameters // ASSERT(psChartWidget); ASSERT(psContext); ASSERT(psChartWidget->psAxisY); // // Get handy pointer to Y axis // psAxisY = psChartWidget->psAxisY; // // Find the range of Y axis in Y axis units // i32GridRange = psAxisY->i32Max - psAxisY->i32Min; // // Find the range of the Y axis in display units (pixels) // i32DispRange = (psContext->sClipRegion.i16YMax - psContext->sClipRegion.i16YMin); // // Find the minimum Y units value to be shown, and the maximum of the // clipping region. // i32GridMin = psAxisY->i32Min; i32DispMax = psContext->sClipRegion.i16YMax; // // Set the fg color for the rectangle fill to match what we want as the // chart background. // GrContextForegroundSet(psContext, psChartWidget->ui32BackgroundColor); GrRectFill(psContext, &psContext->sClipRegion); // // Draw vertical grid lines // GrContextForegroundSet(psContext, psChartWidget->ui32GridColor); for(i32X = psChartWidget->i32GridX; i32X < psContext->sClipRegion.i16XMax; i32X += psChartWidget->psAxisX->i32GridInterval) { GrLineDrawV(psContext, psContext->sClipRegion.i16XMax - i32X, psContext->sClipRegion.i16YMin, psContext->sClipRegion.i16YMax); } // // Draw horizontal grid lines // for(i32Ygrid = psAxisY->i32Min; i32Ygrid < psAxisY->i32Max; i32Ygrid += psAxisY->i32GridInterval) { i32Y = ((i32Ygrid - i32GridMin) * i32DispRange) / i32GridRange; i32Y = i32DispMax - i32Y; GrLineDrawH(psContext, psContext->sClipRegion.i16XMin, psContext->sClipRegion.i16XMax, i32Y); } // // Compute location of Y=0 line, and draw it // i32Y = ((-i32GridMin) * i32DispRange) / i32GridRange; i32Y = i32DispMax - i32Y; GrLineDrawH(psContext, psContext->sClipRegion.i16XMin, psContext->sClipRegion.i16XMax, i32Y); // // Iterate through each series to draw it // psSeries = psChartWidget->psSeries; while(psSeries) { int idx = 0; // // Find the starting X position on the display for this series. // If the series has less data points than can fit on the display // then starting X can be somewhere in the middle of the screen. // i32X = 1 + psContext->sClipRegion.i16XMax - psSeries->ui16NumItems; // // If the starting X is off the left side of the screen, then the // staring index (idx) for reading data needs to be adjusted to the // first value in the series that will be visible on the screen // if(i32X < psContext->sClipRegion.i16XMin) { idx = psContext->sClipRegion.i16XMin - i32X; i32X = psContext->sClipRegion.i16XMin; } // // Set the drawing color for this series // GrContextForegroundSet(psContext, psSeries->ui32Color); // // Scan through all possible X values, find the Y value, and draw the // pixel. // for(; i32X <= psContext->sClipRegion.i16XMax; i32X++) { // // Find the Y value at each position in the data series. Take into // account the data size and the stride // if(psSeries->ui8DataTypeSize == 1) { i32Y = ((int8_t *)psSeries->pvData)[idx * psSeries->ui8Stride]; } else if(psSeries->ui8DataTypeSize == 2) { i32Y = ((int16_t *)psSeries->pvData)[idx * psSeries->ui8Stride]; } else if(psSeries->ui8DataTypeSize == 4) { i32Y = ((int32_t *)psSeries->pvData)[idx * psSeries->ui8Stride]; } else { // // If there is an invalid data size, then just force Y value // to be off the display // i32Y = i32DispMax + 1; break; } // // Advance to the next position in the data series. // idx++; // // Now scale the Y value according to the axis scaling // i32Y = ((i32Y - i32GridMin) * i32DispRange) / i32GridRange; i32Y = i32DispMax - i32Y; // // Draw the pixel on the display // GrPixelDraw(psContext, i32X, i32Y); } // // Advance to the next series until there are no more. // psSeries = psSeries->psNextSeries; } // // Draw a frame around the entire chart. // GrContextForegroundSet(psContext, psChartWidget->ui32Y0Color); GrRectDraw(psContext, &psContext->sClipRegion); // // Draw titles // GrContextForegroundSet(psContext, psChartWidget->ui32TextColor); GrContextFontSet(psContext, psChartWidget->psFont); // // Draw the chart title, if there is one // if(psChartWidget->pcTitle) { GrStringDrawCentered(psContext, psChartWidget->pcTitle, -1, psContext->sClipRegion.i16XMax / 2, GrFontHeightGet(psChartWidget->psFont), 0); } // // Draw the Y axis max label, if there is one // if(psChartWidget->psAxisY->pcMaxLabel) { GrStringDraw(psContext, psChartWidget->psAxisY->pcMaxLabel, -1, psContext->sClipRegion.i16XMin + GrFontMaxWidthGet(psChartWidget->psFont) / 2, GrFontHeightGet(psChartWidget->psFont) / 2, 0); } // // Draw the Y axis min label, if there is one // if(psChartWidget->psAxisY->pcMinLabel) { GrStringDraw(psContext, psChartWidget->psAxisY->pcMinLabel, -1, psContext->sClipRegion.i16XMin + GrFontMaxWidthGet(psChartWidget->psFont) / 2, psContext->sClipRegion.i16YMax - (GrFontHeightGet(psChartWidget->psFont) + (GrFontHeightGet(psChartWidget->psFont) / 2)), 0); } // // Draw a label for the name of the Y axis, if there is one // if(psChartWidget->psAxisY->pcName) { GrStringDraw(psContext, psChartWidget->psAxisY->pcName, -1, psContext->sClipRegion.i16XMin + 1, (psContext->sClipRegion.i16YMax / 2) - (GrFontHeightGet(psChartWidget->psFont) / 2), 1); } }
void window_button(tContext *pContext, uint8_t key, uint8_t icon_type, const char* text) { int width; int i; long forecolor, backcolor; uint8_t upshift = 0; if (key & 0x80) { forecolor = ClrBlack; backcolor = ClrWhite; key &= ~(0x80); } else { forecolor = ClrWhite; backcolor = ClrBlack; } const tRectangle *rect= &button_rect[key]; if((icon_type&0x80) == 0x80) upshift = 13; //Draw button text GrContextFontSet(pContext, &g_sFontBaby16); if (text) { GrContextForegroundSet(pContext, backcolor); if(key == KEY_EXIT) GrStringDraw(pContext, text, -1, rect->sXMax+3, rect->sYMin - upshift , 0); else { width = GrStringWidthGet(pContext, text, -1); if(icon_type == BUTTON_NO_ICON) GrStringDraw(pContext, text, -1, (rect->sXMax - width ), rect->sYMin- upshift , 0); else GrStringDraw(pContext, text, -1, (rect->sXMin - width - 3), rect->sYMin- upshift , 0); } } //Draw button icon image switch(icon_type&0x0f) { case TRIANGLE_UP: for(i=0; i<7;i++) { GrLineDrawH(pContext, rect->sXMin+i, rect->sXMax-i, rect->sYMax - 2 - upshift - i); } break; case TRIANGLE_DOWN: for(i=0; i<7;i++) { GrLineDrawH(pContext, rect->sXMin+i, rect->sXMax-i, rect->sYMin + 2 - upshift + i); } break; case TRIANGLE_RIGHT: for(i=0; i<7;i++) { GrLineDrawV(pContext, rect->sXMin+i, rect->sYMin - upshift +i , rect->sYMax - upshift -i); } break; case TRIANGLE_LEFT: for(i=0; i<7;i++) { GrLineDrawV(pContext, rect->sXMax-i, rect->sYMin - upshift +i , rect->sYMax - upshift -i); } break; case MUSIC_PAUSE: { tRectangle rect1 = {rect->sXMin, rect->sYMin - upshift , rect->sXMin + 3 , rect->sYMax - upshift}; GrRectFill(pContext, &rect1); tRectangle rect2 = {rect->sXMin+6 , rect->sYMin - upshift , rect->sXMin + 9 , rect->sYMax - upshift}; GrRectFill(pContext, &rect2); } break; case MUSIC_NEXT: for(i=0; i<7;i++) { GrLineDrawV(pContext, rect->sXMin+i, rect->sYMin - upshift + i , rect->sYMax - upshift - i); } GrLineDrawV(pContext, rect->sXMax+2, rect->sYMin - upshift , rect->sYMax - upshift ); break; case MUSIC_PREVIOUS: for(i=0; i<7;i++) { GrLineDrawV(pContext, rect->sXMax-i, rect->sYMin- upshift + i , rect->sYMax - upshift -i); } GrLineDrawV(pContext, rect->sXMin-2, rect->sYMin - upshift , rect->sYMax - upshift); break; case BUTTON_NO_ICON: default: break; } }
static void OnDraw(tContext *pContext) { char buf[20]; // clear screen GrContextForegroundSet(pContext, ClrBlack); GrContextBackgroundSet(pContext, ClrWhite); GrRectFill(pContext, &fullscreen_clip); // draw table title GrContextForegroundSet(pContext, ClrWhite); GrContextBackgroundSet(pContext, ClrBlack); const tRectangle rect = {0, 27, 255, 41}; GrRectFill(pContext, &rect); // draw the title bar GrContextFontSet(pContext, &g_sFontGothic18b); sprintf(buf, "%s %d", toMonthName(month, 1), year); GrStringDrawCentered(pContext, buf, -1, LCD_WIDTH / 2, 15, 0); GrContextForegroundSet(pContext, ClrBlack); GrContextBackgroundSet(pContext, ClrWhite); GrContextFontSet(pContext, &g_sFontGothic18); for(int i = 0; i < 7; i++) { GrStringDrawCentered( pContext, week_shortname[i], -1, i * 20 + 11, 35, 0); // draw line in title bar GrLineDrawV(pContext, i * 20, 28, 42); } GrContextFontSet(pContext, &g_sFontGothic18); GrContextForegroundSet(pContext, ClrWhite); GrContextBackgroundSet(pContext, ClrBlack); // get the start point of this month uint8_t weekday = rtc_getweekday(year, month, 1) - 1; // use 0 as index uint8_t maxday = rtc_getmaxday(year, month); uint8_t y = 50; for(int day = 1; day <= maxday; day++) { sprintf(buf, "%d", day); uint8_t today = now_year == year && now_month == month && now_day == day; if (today) { const tRectangle rect = {weekday * 20 + 1, y - 7, 20 + weekday * 20 - 1, y + 7}; GrRectFill(pContext, &rect); GrContextForegroundSet(pContext, ClrBlack); GrContextBackgroundSet(pContext, ClrWhite); } GrStringDrawCentered( pContext, buf, -1, weekday * 20 + 11, y, 0); if (today) { const tRectangle rect2 = {weekday * 20 + 16, y - 5, weekday * 20 + 17, y - 4}; GrRectFill(pContext, &rect2); GrContextForegroundSet(pContext, ClrWhite); GrContextBackgroundSet(pContext, ClrBlack); } if (weekday != 6) GrLineDrawV(pContext, (weekday + 1 ) * 20, 42, y + 7); weekday++; if (weekday == 7) { GrLineDrawH(pContext, 0, LCD_WIDTH, y + 8); weekday = 0; y += 20; } } GrLineDrawH(pContext, 0, weekday * 20, y + 8); // draw the buttons if (month == 1) sprintf(buf, "%s %d", toMonthName(12, 0), year - 1); else sprintf(buf, "%s %d", toMonthName(month - 1, 0), year); window_button(pContext, KEY_ENTER, buf); if (month == 12) sprintf(buf, "%s %d", toMonthName(1, 0), year + 1); else sprintf(buf, "%s %d", toMonthName(month + 1, 0), year); window_button(pContext, KEY_DOWN, buf); }
//***************************************************************************** // //! Draws a line. //! //! \param pContext is a pointer to the drawing context to use. //! \param lX1 is the X coordinate of the start of the line. //! \param lY1 is the Y coordinate of the start of the line. //! \param lX2 is the X coordinate of the end of the line. //! \param lY2 is the Y coordinate of the end of the line. //! //! This function draws a line, utilizing GrLineDrawH() and GrLineDrawV() to //! draw the line as efficiently as possible. The line is clipped to the //! clippping rectangle using the Cohen-Sutherland clipping algorithm, and then //! scan converted using Bresenham's line drawing algorithm. //! //! \return None. // //***************************************************************************** void GrLineFill(const tContext *pContext, long lX1, long lY1, long lX2, long lY2, long width) { long lError, lDeltaX, lDeltaY, lYStep, bSteep; long lWStart, lWEnd; lWEnd = width/2; lWStart = lWEnd - width; // // Check the arguments. // ASSERT(pContext); GrCircleFill(pContext, lX1, lY1, width/2); GrCircleFill(pContext, lX2, lY2, width/2); // // See if this is a vertical line. // if(lX1 == lX2) { // // It is more efficient to avoid Bresenham's algorithm when drawing a // vertical line, so use the vertical line routine to draw this line. // for(long i = lWStart; i <= lWEnd; i++) GrLineDrawV(pContext, lX1 + i, lY1, lY2); // // The line has ben drawn, so return. // return; } // // See if this is a horizontal line. // if(lY1 == lY2) { // // It is more efficient to avoid Bresenham's algorithm when drawing a // horizontal line, so use the horizontal line routien to draw this // line. // for(long i = lWStart; i <= lWEnd; i++) GrLineDrawH(pContext, lX1, lX2, lY1+i); // // The line has ben drawn, so return. // return; } // // Clip this line if necessary, and return without drawing anything if the // line does not cross the clipping region. // if(GrLineClip(pContext, &lX1, &lY1, &lX2, &lY2) == 0) { return; } // // Determine if the line is steep. A steep line has more motion in the Y // direction than the X direction. // if(((lY2 > lY1) ? (lY2 - lY1) : (lY1 - lY2)) > ((lX2 > lX1) ? (lX2 - lX1) : (lX1 - lX2))) { bSteep = 1; } else { bSteep = 0; } // // If the line is steep, then swap the X and Y coordinates. // if(bSteep) { lError = lX1; lX1 = lY1; lY1 = lError; lError = lX2; lX2 = lY2; lY2 = lError; } // // If the starting X coordinate is larger than the ending X coordinate, // then swap the start and end coordinates. // if(lX1 > lX2) { lError = lX1; lX1 = lX2; lX2 = lError; lError = lY1; lY1 = lY2; lY2 = lError; } // // Compute the difference between the start and end coordinates in each // axis. // lDeltaX = lX2 - lX1; lDeltaY = (lY2 > lY1) ? (lY2 - lY1) : (lY1 - lY2); // // Initialize the error term to negative half the X delta. // lError = -lDeltaX / 2; // // Determine the direction to step in the Y axis when required. // if(lY1 < lY2) { lYStep = 1; } else { lYStep = -1; } // // Loop through all the points along the X axis of the line. // for(; lX1 <= lX2; lX1++) { // // See if this is a steep line. // if(bSteep) { // // Plot this point of the line, swapping the X and Y coordinates. // //DpyPixelDraw(pContext->pDisplay, lY1, lX1, pContext->ulForeground); GrLineDrawH(pContext, lY1 + lWStart, lY1 + lWEnd, lX1); } else { // // Plot this point of the line, using the coordinates as is. // //DpyPixelDraw(pContext->pDisplay, lX1, lY1, pContext->ulForeground); GrLineDrawV(pContext, lX1, lY1 + lWStart, lY1 + lWEnd); } // // Increment the error term by the Y delta. // lError += lDeltaY; // // See if the error term is now greater than zero. // if(lError > 0) { // // Take a step in the Y axis. // lY1 += lYStep; // // Decrement the error term by the X delta. // lError -= lDeltaX; } } }