#ifndef _GUISLICE_DRV_SDL_H_ #define _GUISLICE_DRV_SDL_H_ // ======================================================================= // GUIslice library (driver layer for SDL 1.2 & 2.0) // - Calvin Hass // - https://www.impulseadventure.com/elec/guislice-gui.html // - https://github.com/ImpulseAdventure/GUIslice // ======================================================================= // // The MIT License // // Copyright 2016-2020 Calvin Hass // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // // ======================================================================= /// \file GUIslice_drv_sdl.h /// \brief GUIslice library (driver layer for LINUX / SDL) // ======================================================================= // Driver Layer for SDL // ======================================================================= #ifdef __cplusplus extern "C" { #endif // __cplusplus #include "GUIslice.h" #include #if defined(DRV_DISP_SDL1) #include #include #include #endif #if defined(DRV_DISP_SDL2) #include #include #endif // Includes for optional tslib touch handling #if defined(DRV_TOUCH_TSLIB) #include "tslib.h" #endif // ======================================================================= // API support definitions // - These defines indicate whether the driver includes optimized // support for various APIs. If a define is set to 0, then the // GUIslice core emulation will be used instead. // - At the very minimum, the point draw routine must be available: // gslc_DrvDrawPoint() // ======================================================================= #define DRV_HAS_DRAW_POINT 1 ///< Support gslc_DrvDrawPoint() #if defined(DRV_DISP_SDL1) #define DRV_HAS_DRAW_POINTS 1 ///< Support gslc_DrvDrawPoints() #define DRV_HAS_DRAW_LINE 0 ///< Support gslc_DrvDrawLine() #define DRV_HAS_DRAW_RECT_FRAME 0 ///< Support gslc_DrvDrawFrameRect() #define DRV_HAS_DRAW_RECT_FILL 1 ///< Support gslc_DrvDrawFillRect() #define DRV_HAS_DRAW_RECT_ROUND_FRAME 0 ///< Support gslc_DrvDrawFrameRoundRect() #define DRV_HAS_DRAW_RECT_ROUND_FILL 0 ///< Support gslc_DrvDrawFillRoundRect() #define DRV_HAS_DRAW_CIRCLE_FRAME 0 ///< Support gslc_DrvDrawFrameCircle() #define DRV_HAS_DRAW_CIRCLE_FILL 0 ///< Support gslc_DrvDrawFillCircle() #define DRV_HAS_DRAW_TRI_FRAME 0 ///< Support gslc_DrvDrawFrameTriangle() #define DRV_HAS_DRAW_TRI_FILL 0 ///< Support gslc_DrvDrawFillTriangle() #define DRV_HAS_DRAW_TEXT 1 ///< Support gslc_DrvDrawTxt() #define DRV_HAS_DRAW_BMP_MEM 0 ///< Support gslc_DrvDrawBmp24FromMem() #endif #if defined(DRV_DISP_SDL2) #define DRV_HAS_DRAW_POINTS 1 ///< Support gslc_DrvDrawPoints() #define DRV_HAS_DRAW_LINE 1 ///< Support gslc_DrvDrawLine() #define DRV_HAS_DRAW_RECT_FRAME 1 ///< Support gslc_DrvDrawFrameRect() #define DRV_HAS_DRAW_RECT_FILL 1 ///< Support gslc_DrvDrawFillRect() #define DRV_HAS_DRAW_RECT_ROUND_FRAME 0 ///< Support gslc_DrvDrawFrameRoundRect() #define DRV_HAS_DRAW_RECT_ROUND_FILL 0 ///< Support gslc_DrvDrawFillRoundRect() #define DRV_HAS_DRAW_CIRCLE_FRAME 0 ///< Support gslc_DrvDrawFrameCircle() #define DRV_HAS_DRAW_CIRCLE_FILL 0 ///< Support gslc_DrvDrawFillCircle() #define DRV_HAS_DRAW_TRI_FRAME 0 ///< Support gslc_DrvDrawFrameTriangle() #define DRV_HAS_DRAW_TRI_FILL 0 ///< Support gslc_DrvDrawFillTriangle() #define DRV_HAS_DRAW_TEXT 1 ///< Support gslc_DrvDrawTxt() #define DRV_HAS_DRAW_BMP_MEM 0 ///< Support gslc_DrvDrawBmp24FromMem() #endif #define DRV_OVERRIDE_TXT_ALIGN 0 ///< Driver provides text alignment // ======================================================================= // Driver-specific members // ======================================================================= typedef struct { #if defined(DRV_DISP_SDL1) SDL_Surface* pSurfScreen; ///< Surface ptr for screen #endif #if defined(DRV_DISP_SDL2) SDL_Window* pWind; ///< SDL2 Window SDL_Renderer* pRender; ///< SDL2 Rendering engine #endif #if defined(DRV_TOUCH_TSLIB) struct tsdev* pTsDev; ///< Ptr to touchscreen device #endif } gslc_tsDriver; // ======================================================================= // Public APIs to GUIslice core library // - These functions define the renderer / driver-dependent // implementations for the core drawing operations within // GUIslice. // ======================================================================= // ----------------------------------------------------------------------- // Configuration Functions // ----------------------------------------------------------------------- /// /// Initialize the SDL library /// - Performs clean startup workaround (if enabled) /// - Configures video mode /// - Initializes font support /// /// PRE: /// - The environment variables should be configured before /// calling gslc_DrvInit(). /// /// /// \param[in] pGui: Pointer to GUI /// /// \return true if success, false if fail /// bool gslc_DrvInit(gslc_tsGui* pGui); /// /// Free up any members associated with the driver /// - Eg. renderers, windows, background surfaces, etc. /// /// \param[in] pGui: Pointer to GUI /// /// \return none /// void gslc_DrvDestruct(gslc_tsGui* pGui); /// /// Get the display driver name /// /// \param[in] pGui: Pointer to GUI /// /// \return String containing driver name /// const char* gslc_DrvGetNameDisp(gslc_tsGui* pGui); /// /// Get the touch driver name /// /// \param[in] pGui: Pointer to GUI /// /// \return String containing driver name /// const char* gslc_DrvGetNameTouch(gslc_tsGui* pGui); /// /// Get the native display driver instance /// - This can be useful to access special commands /// available in the selected driver. /// /// \param[in] pGui: Pointer to GUI /// /// \return Void pointer to the display driver instance. /// This pointer should be typecast to the particular /// driver being used. If no driver was created then /// this function will return NULL. /// void* gslc_DrvGetDriverDisp(gslc_tsGui* pGui); /// /// Get the native touch driver instance /// - This can be useful to access special commands /// available in the selected driver. /// /// \param[in] pGui: Pointer to GUI /// /// \return Void pointer to the touch driver instance. /// This pointer should be typecast to the particular /// driver being used. If no driver was created then /// this function will return NULL. /// void* gslc_DrvGetDriverTouch(gslc_tsGui* pGui); // ----------------------------------------------------------------------- // Image/surface handling Functions // ----------------------------------------------------------------------- /// /// Load a bitmap (*.bmp) and create a new image resource. /// Transparency is enabled by GSLC_BMP_TRANS_EN /// through use of color (GSLC_BMP_TRANS_RGB). /// /// \param[in] pGui: Pointer to GUI /// \param[in] sImgRef: Image reference /// /// \return Image pointer (surface/texture/path) or NULL if error /// void* gslc_DrvLoadImage(gslc_tsGui* pGui,gslc_tsImgRef sImgRef); /// /// Configure the background to use a bitmap image /// - The background is used when redrawing the entire page /// /// \param[in] pGui: Pointer to GUI /// \param[in] sImgRef: Image reference /// /// \return true if success, false if fail /// bool gslc_DrvSetBkgndImage(gslc_tsGui* pGui,gslc_tsImgRef sImgRef); /// /// Configure the background to use a solid color /// - The background is used when redrawing the entire page /// /// \param[in] pGui: Pointer to GUI /// \param[in] nCol: RGB Color to use /// /// \return true if success, false if fail /// bool gslc_DrvSetBkgndColor(gslc_tsGui* pGui,gslc_tsColor nCol); /// /// Set an element's normal-state image /// /// \param[in] pGui: Pointer to GUI /// \param[in] pElem: Pointer to Element to update /// \param[in] sImgRef: Image reference /// /// \return true if success, false if error /// bool gslc_DrvSetElemImageNorm(gslc_tsGui* pGui,gslc_tsElem* pElem,gslc_tsImgRef sImgRef); /// /// Set an element's glow-state image /// /// \param[in] pGui: Pointer to GUI /// \param[in] pElem: Pointer to Element to update /// \param[in] sImgRef: Image reference /// /// \return true if success, false if error /// bool gslc_DrvSetElemImageGlow(gslc_tsGui* pGui,gslc_tsElem* pElem,gslc_tsImgRef sImgRef); /// /// Release an image surface /// /// \param[in] pvImg: Void ptr to image /// /// \return none /// void gslc_DrvImageDestruct(void* pvImg); /// /// Set the clipping rectangle for future drawing updates /// /// \param[in] pGui: Pointer to GUI /// \param[in] pRect: Rectangular region to constrain edits /// /// \return true if success, false if error /// bool gslc_DrvSetClipRect(gslc_tsGui* pGui,gslc_tsRect* pRect); // ----------------------------------------------------------------------- // Font handling Functions // ----------------------------------------------------------------------- /// /// Load a font from a resource and return pointer to it /// /// \param[in] eFontRefType: Font reference type (GSLC_FONTREF_FNAME for SDL) /// \param[in] pvFontRef: Font reference pointer (Pointer to the font filename) /// \param[in] nFontSz: Typeface size to use /// /// \return Void ptr to driver-specific font if load was successful, NULL otherwise /// const void* gslc_DrvFontAdd(gslc_teFontRefType eFontRefType,const void* pvFontRef,uint16_t nFontSz); /// /// Release all fonts defined in the GUI /// /// \param[in] pGui: Pointer to GUI /// /// \return none /// void gslc_DrvFontsDestruct(gslc_tsGui* pGui); /// /// Get the extent (width and height) of a text string /// /// \param[in] pGui: Pointer to GUI /// \param[in] pFont: Ptr to Font structure /// \param[in] pStr: String to display /// \param[in] eTxtFlags: Flags associated with text string /// \param[out] pnTxtX: Ptr to offset X of text /// \param[out] pnTxtY: Ptr to offset Y of text /// \param[out] pnTxtSzW: Ptr to width of text /// \param[out] pnTxtSzH: Ptr to height of text /// /// \return true if success, false if failure /// bool gslc_DrvGetTxtSize(gslc_tsGui* pGui,gslc_tsFont* pFont,const char* pStr,gslc_teTxtFlags eTxtFlags, int16_t* pnTxtX,int16_t* pnTxtY,uint16_t* pnTxtSzW,uint16_t* pnTxtSzH); /// /// Draw a text string at the given coordinate /// /// \param[in] pGui: Pointer to GUI /// \param[in] nTxtX: X coordinate of top-left text string /// \param[in] nTxtY: Y coordinate of top-left text string /// \param[in] pFont: Ptr to Font /// \param[in] pStr: String to display /// \param[in] eTxtFlags: Flags associated with text string /// \param[in] colTxt: Color to draw text /// \param[in] colBg: unused in SDL, defaults to black /// /// \return true if success, false if failure /// bool gslc_DrvDrawTxt(gslc_tsGui* pGui,int16_t nTxtX,int16_t nTxtY,gslc_tsFont* pFont,const char* pStr,gslc_teTxtFlags eTxtFlags,gslc_tsColor colTxt,gslc_tsColor colBg); // ----------------------------------------------------------------------- // Screen Management Functions // ----------------------------------------------------------------------- /// /// Force a page flip to occur. This generally copies active /// screen surface to the display. /// /// \param[in] pGui: Pointer to GUI /// /// \return none /// void gslc_DrvPageFlipNow(gslc_tsGui* pGui); // ----------------------------------------------------------------------- // Graphics Primitives Functions // ----------------------------------------------------------------------- /// /// Draw a point /// /// \param[in] pGui: Pointer to GUI /// \param[in] nX: X coordinate of point /// \param[in] nY: Y coordinate of point /// \param[in] nCol: Color RGB value to draw /// /// \return true if success, false if error /// bool gslc_DrvDrawPoint(gslc_tsGui* pGui,int16_t nX,int16_t nY,gslc_tsColor nCol); /// /// Draw a point /// /// \param[in] pGui: Pointer to GUI /// \param[in] asPt: Array of points to draw /// \param[in] nNumPt: Number of points in array /// \param[in] nCol: Color RGB value to draw /// /// \return true if success, false if error /// bool gslc_DrvDrawPoints(gslc_tsGui* pGui,gslc_tsPt* asPt,uint16_t nNumPt,gslc_tsColor nCol); /// /// Draw a framed rectangle /// /// \param[in] pGui: Pointer to GUI /// \param[in] rRect: Rectangular region to frame /// \param[in] nCol: Color RGB value to frame /// /// \return true if success, false if error /// bool gslc_DrvDrawFrameRect(gslc_tsGui* pGui,gslc_tsRect rRect,gslc_tsColor nCol); /// /// Draw a filled rectangle /// /// \param[in] pGui: Pointer to GUI /// \param[in] rRect: Rectangular region to fill /// \param[in] nCol: Color RGB value to fill /// /// \return true if success, false if error /// bool gslc_DrvDrawFillRect(gslc_tsGui* pGui,gslc_tsRect rRect,gslc_tsColor nCol); /// /// Draw a line /// /// \param[in] pGui: Pointer to GUI /// \param[in] nX0: Line start (X coordinate) /// \param[in] nY0: Line start (Y coordinate) /// \param[in] nX1: Line finish (X coordinate) /// \param[in] nY1: Line finish (Y coordinate) /// \param[in] nCol: Color RGB value to draw /// /// \return true if success, false if error /// bool gslc_DrvDrawLine(gslc_tsGui* pGui,int16_t nX0,int16_t nY0,int16_t nX1,int16_t nY1,gslc_tsColor nCol); // TODO: Add DrvDrawFrameCircle() // TODO: Add DrvDrawFillCircle() // TODO: Add DrvDrawFrameTriangle() // TODO: Add DrvDrawFillTriangle() /// /// Copy all of source image to destination screen at specified coordinate /// /// \param[in] pGui: Pointer to GUI /// \param[in] nDstX: Destination X coord for copy /// \param[in] nDstY: Destination Y coord for copy /// \param[in] sImgRef: Image reference /// /// \return true if success, false if fail /// bool gslc_DrvDrawImage(gslc_tsGui* pGui,int16_t nDstX,int16_t nDstY,gslc_tsImgRef sImgRef); // TODO: Add DrvDrawMonoFromMem() // TODO: Add DrvDrawBmp24FromMem() /// /// Copy the background image to destination screen /// /// \param[in] pGui: Pointer to GUI /// /// \return true if success, false if fail /// void gslc_DrvDrawBkgnd(gslc_tsGui* pGui); // ----------------------------------------------------------------------- // Touch Functions // ----------------------------------------------------------------------- /// /// Get the last touch event from the SDL_Event handler /// /// \param[in] pGui: Pointer to GUI /// \param[out] pnX: Ptr to X coordinate of last touch event /// \param[out] pnY: Ptr to Y coordinate of last touch event /// \param[out] pnPress: Ptr to Pressure level of last touch event (0 for none, 1 for touch) /// \param[out] peInputEvent Indication of event type /// \param[out] pnInputVal Additional data for event type /// /// \return true if an event was detected or false otherwise /// bool gslc_DrvGetTouch(gslc_tsGui* pGui,int16_t* pnX,int16_t* pnY,uint16_t* pnPress,gslc_teInputRawEvent* peInputEvent,int16_t* pnInputVal); // ----------------------------------------------------------------------- // Dynamic Screen rotation and Touch axes swap/flip functions // ----------------------------------------------------------------------- /// /// Change rotation, automatically adapt touchscreen axes swap/flip /// /// \param[in] pGui: Pointer to GUI /// \param[in] nRotation: Screen Rotation value (0, 1, 2 or 3) /// /// \return true if successful /// bool gslc_DrvRotate(gslc_tsGui* pGui, uint8_t nRotation); // ======================================================================= // Private Functions // - These functions are not included in the scope of APIs used by // the core GUIslice library. Instead, these functions are used // to support the operations within this driver layer. // ======================================================================= // ----------------------------------------------------------------------- // Private Configuration Functions // ----------------------------------------------------------------------- /// /// Ensure SDL initializes cleanly to workaround /// possible issues if previous SDL application /// failed to close down gracefully. /// /// \param[in] sTTY: Terminal device (eg. "/dev/tty0") /// /// \return true if success /// bool gslc_DrvCleanStart(const char* sTTY); /// /// Report driver debug info (before initialization) /// /// \return none /// void gslc_DrvReportInfoPre(); /// /// Report driver debug info (after initialization) /// /// \return none /// void gslc_DrvReportInfoPost(); // ----------------------------------------------------------------------- // Private Conversion Functions // ----------------------------------------------------------------------- /// /// Translate a gslc_tsRect into an SDL_Rect /// /// \param[in] rRect: gslc_tsRect /// /// \return Converted SDL_Rect /// SDL_Rect gslc_DrvAdaptRect(gslc_tsRect rRect); /// /// Translate a gslc_tsColor into an SDL_Color /// /// \param[in] sCol: gslc_tsColor /// /// \return Converted SDL_Color /// SDL_Color gslc_DrvAdaptColor(gslc_tsColor sCol); // ----------------------------------------------------------------------- // Private Drawing Functions // ----------------------------------------------------------------------- #if defined(DRV_DISP_SDL1) /// /// Lock an SDL surface so that direct pixel manipulation /// can be done safely. This function is called before any /// direct pixel updates. /// /// POST: /// - Primary screen surface is locked /// /// \param[in] pGui: Pointer to GUI /// /// \return true if success, false otherwise /// bool gslc_DrvScreenLock(gslc_tsGui* pGui); /// /// Unlock the SDL surface after pixel manipulation is /// complete. This function is called after all pixel updates /// are done. /// /// POST: /// - Primary screen surface is unlocked /// /// \param[in] pGui: Pointer to GUI /// /// \return none /// void gslc_DrvScreenUnlock(gslc_tsGui* pGui); /// /// Convert an RGB color triplet into the surface pixel value. /// This is called to produce the native pixel value required by /// the raw pixel manipulation routines. /// /// \param[in] pGui: Pointer to GUI /// \param[in] nCol: RGB value for conversion /// /// \return A pixel value for the current screen format /// uint32_t gslc_DrvAdaptColorRaw(gslc_tsGui* pGui,gslc_tsColor nCol); /// /// Get the pixel at (X,Y) from the active screen /// /// PRE: /// - Screen surface must be locked /// /// \param[in] pGui: Pointer to GUI /// \param[in] nX: Pixel X coordinate /// \param[in] nY: Pixel Y coordinate /// /// \return Pixel color value from the coordinate or 0 if error /// uint32_t gslc_DrvDrawGetPixelRaw(gslc_tsGui* pGui,int16_t nX,int16_t nY); /// /// Set a pixel on the active screen to the given color /// /// PRE: /// - Screen surface must be locked /// /// \param[in] pGui: Pointer to GUI /// \param[in] nX: Pixel X coordinate to set /// \param[in] nY: Pixel Y coordinate to set /// \param[in] nPixelCol: Raw color pixel value to assign /// /// \return none /// void gslc_DrvDrawSetPixelRaw(gslc_tsGui* pGui,int16_t nX,int16_t nY,uint32_t nPixelCol); /// /// Copy one image region to another. /// - This is typically used to copy an image to the main screen surface /// /// \param[in] pGui: Pointer to GUI /// \param[in] nX: Destination X coordinate of copy /// \param[in] nY: Destination Y coordinate of copy /// \param[in] pvSrc: Void Ptr to source surface (eg. a loaded image) /// \param[in] pvDest: Void Ptr to destination surface (typically the screen) /// /// \return none /// void gslc_DrvPasteSurface(gslc_tsGui* pGui,int16_t nX, int16_t nY, void* pvSrc, void* pvDest); #endif // DRV_DISP_SDL1 // ----------------------------------------------------------------------- // Private Touchscreen Functions (if using SDL) // ----------------------------------------------------------------------- /// /// Perform any touchscreen-specific initialization /// /// \param[in] pGui: Pointer to GUI /// \param[in] acDev: Device path to touchscreen /// eg. "/dev/input/touchscreen" /// /// \return true if successful /// bool gslc_DrvInitTouch(gslc_tsGui* pGui,const char* acDev); // ----------------------------------------------------------------------- // Touchscreen Functions (if using tslib) // ----------------------------------------------------------------------- #if defined(DRV_TOUCH_TSLIB) /// /// Perform any touchscreen-specific initialization /// /// \param[in] pGui: Pointer to GUI /// \param[in] acDev: Device path to touchscreen /// eg. "/dev/input/touchscreen" /// /// \return true if successful /// bool gslc_TDrvInitTouch(gslc_tsGui* pGui,const char* acDev); /// /// Get the last touch event from the tslib handler /// /// \param[in] pGui: Pointer to GUI /// \param[out] pnX: Ptr to X coordinate of last touch event /// \param[out] pnY: Ptr to Y coordinate of last touch event /// \param[out] pnPress: Ptr to Pressure level of last touch event (0 for none, >0 for touch) /// \param[out] peInputEvent Indication of event type /// \param[out] pnInputVal Additional data for event type /// /// \return non-zero if an event was detected or 0 otherwise /// bool gslc_TDrvGetTouch(gslc_tsGui* pGui, int16_t* pnX, int16_t* pnY, uint16_t* pnPress, gslc_teInputRawEvent* peInputEvent, int16_t* pnInputVal); #endif // DRV_TOUCH_TSLIB #ifdef __cplusplus } #endif // __cplusplus #endif // _GUISLICE_DRV_SDL_H_