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.

453 lines
19 KiB

  1. // Copyright 2021 Nick Brassel (@tzarc)
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. #include <stdint.h>
  5. #include <stdbool.h>
  6. #include "deferred_exec.h"
  7. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  8. // Quantum Painter global configurables (add to your keyboard's config.h)
  9. #ifndef QUANTUM_PAINTER_NUM_IMAGES
  10. /**
  11. * @def This controls the maximum number of images that Quantum Painter can load at any one time. Images can be loaded
  12. * using \ref qp_load_image_mem, and can be unloaded by calling \ref qp_close_image. Increasing this number in
  13. * order to load more images increases the amount of RAM required. Image data is not held in RAM, just metadata.
  14. */
  15. # define QUANTUM_PAINTER_NUM_IMAGES 8
  16. #endif // QUANTUM_PAINTER_NUM_IMAGES
  17. #ifndef QUANTUM_PAINTER_NUM_FONTS
  18. /**
  19. * @def This controls the maximum number of fonts that Quantum Painter can load. Fonts can be loaded using
  20. * \ref qp_load_font_mem, and can be unloaded by calling \ref qp_close_font. Increasing this number in order to
  21. * load more fonts increases the amount of RAM required. Font data is not held in RAM, unless
  22. * \ref QUANTUM_PAINTER_LOAD_FONTS_TO_RAM is set to TRUE.
  23. */
  24. # define QUANTUM_PAINTER_NUM_FONTS 4
  25. #endif // QUANTUM_PAINTER_NUM_FONTS
  26. #ifndef QUANTUM_PAINTER_LOAD_FONTS_TO_RAM
  27. /**
  28. * @def This controls whether or not fonts should be cached in RAM. Under normal circumstances, fonts can have quite
  29. * random access patterns, and due to timing of flash memory or external storage, it may be a significant speedup
  30. * moving the font into RAM before use. Defaults to "off", but if it's enabled it will fallback to reading from the
  31. * original location if corresponding RAM could not be allocated (such as being too large).
  32. */
  33. # define QUANTUM_PAINTER_LOAD_FONTS_TO_RAM FALSE
  34. #endif
  35. #ifndef QUANTUM_PAINTER_CONCURRENT_ANIMATIONS
  36. /**
  37. * @def This controls the maximum number of animations that Quantum Painter can play simultaneously. Increasing this
  38. * number in order to play more animations at the same time increases the amount of RAM required.
  39. */
  40. # define QUANTUM_PAINTER_CONCURRENT_ANIMATIONS 4
  41. #endif // QUANTUM_PAINTER_CONCURRENT_ANIMATIONS
  42. #ifndef QUANTUM_PAINTER_PIXDATA_BUFFER_SIZE
  43. /**
  44. * @def This controls the maximum size of the pixel data buffer used for single blocks of transmission. Larger buffers
  45. * means more data is processed at one time, with less frequent transmissions, at the cost of RAM.
  46. */
  47. # define QUANTUM_PAINTER_PIXDATA_BUFFER_SIZE 32
  48. #endif
  49. #ifndef QUANTUM_PAINTER_SUPPORTS_256_PALETTE
  50. /**
  51. * @def This controls whether 256-color palettes are supported. This has relatively hefty requirements on RAM -- at
  52. * least 1kB extra is required just to store the palette information, with more required for other metadata.
  53. */
  54. # define QUANTUM_PAINTER_SUPPORTS_256_PALETTE FALSE
  55. #endif
  56. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  57. // Quantum Painter types
  58. /**
  59. * @typedef A handle to a Quantum Painter device, such as an LCD or OLED. Most Quantum Painter APIs require this
  60. * argument in order to perform operations on the display.
  61. */
  62. typedef const void *painter_device_t;
  63. /**
  64. * @typedef The desired rotation of a panel. Used as a parameter to \ref qp_init, and can be queried by
  65. * \ref qp_get_geometry.
  66. */
  67. typedef enum { QP_ROTATION_0, QP_ROTATION_90, QP_ROTATION_180, QP_ROTATION_270 } painter_rotation_t;
  68. /**
  69. * @typedef A descriptor for a Quantum Painter image.
  70. */
  71. typedef struct painter_image_desc_t {
  72. uint16_t width; ///< Image width
  73. uint16_t height; ///< Image height
  74. uint16_t frame_count; ///< Number of frames in this image
  75. } painter_image_desc_t;
  76. /**
  77. * @typedef A handle to a Quantum Painter image.
  78. */
  79. typedef const painter_image_desc_t *painter_image_handle_t;
  80. /**
  81. * @typedef A descriptor for a Quantum Painter font.
  82. */
  83. typedef struct painter_font_desc_t {
  84. uint8_t line_height; ///< The number of pixels in height for each line
  85. } painter_font_desc_t;
  86. /**
  87. * @typedef A handle to a Quantum Painter font.
  88. */
  89. typedef const painter_font_desc_t *painter_font_handle_t;
  90. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  91. // Quantum Painter External API
  92. /**
  93. * Initialize a device and set its rotation.
  94. *
  95. * @param device[in] the handle of the device to initialize
  96. * @param rotation[in] the rotation to use
  97. * @return true if initialization succeeded
  98. * @return false if initialization failed
  99. */
  100. bool qp_init(painter_device_t device, painter_rotation_t rotation);
  101. /**
  102. * Controls whether a display is on or off.
  103. *
  104. * @note If backlighting is used to control brightness (such as for an LCD), it will need to be handled external to
  105. * Quantum Painter.
  106. *
  107. * @param device[in] the handle of the device to control
  108. * @param power_on[in] whether or not the device should be on
  109. * @return true if controlling the power state succeeded
  110. * @return false if controlling the power state failed
  111. */
  112. bool qp_power(painter_device_t device, bool power_on);
  113. /**
  114. * Clears a device's screen.
  115. *
  116. * @param device[in] the handle of the device to control
  117. * @return true if clearing the screen succeeded
  118. * @return false if clearing the screen failed
  119. */
  120. bool qp_clear(painter_device_t device);
  121. /**
  122. * Transmits any outstanding data to the screen in order to persist all changes to the display.
  123. *
  124. * @note Drivers without internal framebuffers will likely ignore this API.
  125. *
  126. * @param device[in] the handle of the device to control
  127. * @return true if flushing changes to the screen succeeded
  128. * @return false if flushing changes to the screen failed
  129. */
  130. bool qp_flush(painter_device_t device);
  131. /**
  132. * Retrieves the size, rotation, and offsets for the display.
  133. *
  134. * @note Any arguments of NULL will be ignored.
  135. *
  136. * @param device[in] the handle of the device to control
  137. * @param width[out] the device's width
  138. * @param height[out] the device's height
  139. * @param rotation[out] the device's rotation
  140. * @param offset_x[out] the device's x-offset applied while drawing
  141. * @param offset_y[out] the device's y-offset applied while drawing
  142. */
  143. void qp_get_geometry(painter_device_t device, uint16_t *width, uint16_t *height, painter_rotation_t *rotation, uint16_t *offset_x, uint16_t *offset_y);
  144. /**
  145. * Allows repositioning of the viewport if the panel geometry offsets are non-zero.
  146. *
  147. * @param device[in] the handle of the device to control
  148. * @param offset_x[in] the device's x-offset applied while drawing
  149. * @param offset_y[in] the device's y-offset applied while drawing
  150. */
  151. void qp_set_viewport_offsets(painter_device_t device, uint16_t offset_x, uint16_t offset_y);
  152. /**
  153. * Sets a pixel to the specified color.
  154. *
  155. * @param device[in] the handle of the device to control
  156. * @param x[in] the x-position to draw onto the device
  157. * @param y[in] the y-position to draw onto the device
  158. * @param hue[in] the hue to use, with 0-360 mapped to 0-255
  159. * @param sat[in] the saturation to use, with 0-100% mapped to 0-255
  160. * @param val[in] the value to use, with 0-100% mapped to 0-255
  161. * @return true if setting the pixel succeeded
  162. * @return false if setting the pixel failed
  163. */
  164. bool qp_setpixel(painter_device_t device, uint16_t x, uint16_t y, uint8_t hue, uint8_t sat, uint8_t val);
  165. /**
  166. * Draws a line using the specified color.
  167. *
  168. * @param device[in] the handle of the device to control
  169. * @param x0[in] the device's x-position to start
  170. * @param y0[in] the device's y-position to start
  171. * @param x1[in] the device's x-position to finish
  172. * @param y1[in] the device's y-position to finish
  173. * @param hue[in] the hue to use, with 0-360 mapped to 0-255
  174. * @param sat[in] the saturation to use, with 0-100% mapped to 0-255
  175. * @param val[in] the value to use, with 0-100% mapped to 0-255
  176. * @return true if drawing the line succeeded
  177. * @return false if drawing the line failed
  178. */
  179. bool qp_line(painter_device_t device, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint8_t hue, uint8_t sat, uint8_t val);
  180. /**
  181. * Draws a rectangle using the specified color, optionally filled.
  182. *
  183. * @param device[in] the handle of the device to control
  184. * @param left[in] the device's x-position to start
  185. * @param top[in] the device's y-position to start
  186. * @param right[in] the device's x-position to finish
  187. * @param bottom[in] the device's y-position to finish
  188. * @param hue[in] the hue to use, with 0-360 mapped to 0-255
  189. * @param sat[in] the saturation to use, with 0-100% mapped to 0-255
  190. * @param val[in] the value to use, with 0-100% mapped to 0-255
  191. * @param filled[in] whether the rectangle should be filled
  192. * @return true if drawing the rectangle succeeded
  193. * @return false if drawing the rectangle failed
  194. */
  195. bool qp_rect(painter_device_t device, uint16_t left, uint16_t top, uint16_t right, uint16_t bottom, uint8_t hue, uint8_t sat, uint8_t val, bool filled);
  196. /**
  197. * Draws a circle using the specified color, optionally filled.
  198. *
  199. * @param device[in] the handle of the device to control
  200. * @param x[in] the x-position of the centre of the circle to draw onto the device
  201. * @param y[in] the y-position of the centre of the circle to draw onto the device
  202. * @param radius[in] the radius of the circle to draw
  203. * @param hue[in] the hue to use, with 0-360 mapped to 0-255
  204. * @param sat[in] the saturation to use, with 0-100% mapped to 0-255
  205. * @param val[in] the value to use, with 0-100% mapped to 0-255
  206. * @param filled[in] whether the circle should be filled
  207. * @return true if drawing the circle succeeded
  208. * @return false if drawing the circle failed
  209. */
  210. bool qp_circle(painter_device_t device, uint16_t x, uint16_t y, uint16_t radius, uint8_t hue, uint8_t sat, uint8_t val, bool filled);
  211. /**
  212. * Draws a ellipse using the specified color, optionally filled.
  213. *
  214. * @param device[in] the handle of the device to control
  215. * @param x[in] the x-position of the centre of the ellipse to draw onto the device
  216. * @param y[in] the y-position of the centre of the ellipse to draw onto the device
  217. * @param sizex[in] the horizontal size of the ellipse
  218. * @param sizey[in] the vertical size of the ellipse
  219. * @param hue[in] the hue to use, with 0-360 mapped to 0-255
  220. * @param sat[in] the saturation to use, with 0-100% mapped to 0-255
  221. * @param val[in] the value to use, with 0-100% mapped to 0-255
  222. * @param filled[in] whether the ellipse should be filled
  223. * @return true if drawing the ellipse succeeded
  224. * @return false if drawing the ellipse failed
  225. */
  226. bool qp_ellipse(painter_device_t device, uint16_t x, uint16_t y, uint16_t sizex, uint16_t sizey, uint8_t hue, uint8_t sat, uint8_t val, bool filled);
  227. /**
  228. * Sets up the location on the display to stream raw pixel data to the display, using \ref qp_pixdata.
  229. *
  230. * @note This is for advanced uses only, and should not be required for normal Quantum Painter functionality.
  231. *
  232. * @param device[in] the handle of the device to control
  233. * @param left[in] the device's x-position to start
  234. * @param top[in] the device's y-position to start
  235. * @param right[in] the device's x-position to finish
  236. * @param bottom[in] the device's y-position to finish
  237. * @return true if setting the viewport succeeded
  238. * @return false if setting the viewport failed
  239. */
  240. bool qp_viewport(painter_device_t device, uint16_t left, uint16_t top, uint16_t right, uint16_t bottom);
  241. /**
  242. * Streams raw pixel data (in the native panel format) to the area previously set by \ref qp_viewport.
  243. *
  244. * @note This is for advanced uses only, and should not be required for normal Quantum Painter functionality.
  245. *
  246. * @param device[in] the handle of the device to control
  247. * @param pixel_data[in] pointer to buffer data
  248. * @param native_pixel_count[in] the number of pixels to transmit
  249. * @return true if streaming of data succeeded
  250. * @return false if streaming of data failed
  251. */
  252. bool qp_pixdata(painter_device_t device, const void *pixel_data, uint32_t native_pixel_count);
  253. /**
  254. * Loads an image into memory.
  255. *
  256. * @note Images can be unloaded by calling \ref qp_close_image.
  257. *
  258. * @param buffer[in] the image data to load
  259. * @return an image handle usable with \ref qp_drawimage, \ref qp_drawimage_recolor, \ref qp_animate, and
  260. * \ref qp_animate_recolor.
  261. * @return NULL if loading the image failed
  262. */
  263. painter_image_handle_t qp_load_image_mem(const void *buffer);
  264. /**
  265. * Closes an image handle when no longer in use.
  266. *
  267. * @param image[in] the handle of the image to unload
  268. * @return true if unloading the image succeeded
  269. * @return false if unloading the image failed
  270. */
  271. bool qp_close_image(painter_image_handle_t image);
  272. /**
  273. * Draws an image to the display.
  274. *
  275. * @param device[in] the handle of the device to control
  276. * @param x[in] the x-position where the image should be drawn onto the device
  277. * @param y[in] the y-position where the image should be drawn onto the device
  278. * @param image[in] the handle of the image to draw
  279. * @return true if drawing the image succeeded
  280. * @return false if drawing the image failed
  281. */
  282. bool qp_drawimage(painter_device_t device, uint16_t x, uint16_t y, painter_image_handle_t image);
  283. /**
  284. * Draws an image to the display, recoloring monochrome images to the desired foreground/background.
  285. *
  286. * @param device[in] the handle of the device to control
  287. * @param x[in] the x-position where the image should be drawn onto the device
  288. * @param y[in] the y-position where the image should be drawn onto the device
  289. * @param image[in] the handle of the image to draw
  290. * @param hue_fg[in] the foreground hue to use, with 0-360 mapped to 0-255
  291. * @param sat_fg[in] the foreground saturation to use, with 0-100% mapped to 0-255
  292. * @param val_fg[in] the foreground value to use, with 0-100% mapped to 0-255
  293. * @param hue_bg[in] the background hue to use, with 0-360 mapped to 0-255
  294. * @param sat_bg[in] the background saturation to use, with 0-100% mapped to 0-255
  295. * @param val_bg[in] the background value to use, with 0-100% mapped to 0-255
  296. * @return true if drawing the image succeeded
  297. * @return false if drawing the image failed
  298. */
  299. bool qp_drawimage_recolor(painter_device_t device, uint16_t x, uint16_t y, painter_image_handle_t image, uint8_t hue_fg, uint8_t sat_fg, uint8_t val_fg, uint8_t hue_bg, uint8_t sat_bg, uint8_t val_bg);
  300. /**
  301. * Draws an animation to the display.
  302. *
  303. * @param device[in] the handle of the device to control
  304. * @param x[in] the x-position where the image should be drawn onto the device
  305. * @param y[in] the y-position where the image should be drawn onto the device
  306. * @param image[in] the handle of the image to draw
  307. * @return the \ref deferred_token to use with \ref qp_stop_animation in order to stop animating
  308. * @return INVALID_DEFERRED_TOKEN if animating the image failed
  309. */
  310. deferred_token qp_animate(painter_device_t device, uint16_t x, uint16_t y, painter_image_handle_t image);
  311. /**
  312. * Draws an animation to the display, recoloring monochrome images to the desired foreground/background.
  313. *
  314. * @param device[in] the handle of the device to control
  315. * @param x[in] the x-position where the image should be drawn onto the device
  316. * @param y[in] the y-position where the image should be drawn onto the device
  317. * @param image[in] the handle of the image to draw
  318. * @param hue_fg[in] the foreground hue to use, with 0-360 mapped to 0-255
  319. * @param sat_fg[in] the foreground saturation to use, with 0-100% mapped to 0-255
  320. * @param val_fg[in] the foreground value to use, with 0-100% mapped to 0-255
  321. * @param hue_bg[in] the background hue to use, with 0-360 mapped to 0-255
  322. * @param sat_bg[in] the background saturation to use, with 0-100% mapped to 0-255
  323. * @param val_bg[in] the background value to use, with 0-100% mapped to 0-255
  324. * @return the \ref deferred_token to use with \ref qp_stop_animation in order to stop animating
  325. * @return INVALID_DEFERRED_TOKEN if animating the image failed
  326. */
  327. deferred_token qp_animate_recolor(painter_device_t device, uint16_t x, uint16_t y, painter_image_handle_t image, uint8_t hue_fg, uint8_t sat_fg, uint8_t val_fg, uint8_t hue_bg, uint8_t sat_bg, uint8_t val_bg);
  328. /**
  329. * Cancels a running animation.
  330. *
  331. * @param anim_token[in] the animation token returned by \ref qp_animate, or \ref qp_animate_recolor.
  332. */
  333. void qp_stop_animation(deferred_token anim_token);
  334. /**
  335. * Loads a font into memory.
  336. *
  337. * @note Fonts can be unloaded by calling \ref qp_close_font.
  338. *
  339. * @param buffer[in] the font data to load
  340. * @return an image handle usable with \ref qp_textwidth, \ref qp_drawtext, and \ref qp_drawtext_recolor.
  341. * @return NULL if loading the font failed
  342. */
  343. painter_font_handle_t qp_load_font_mem(const void *buffer);
  344. /**
  345. * Closes a font handle when no longer in use.
  346. *
  347. * @param font[in] the handle of the font to unload
  348. * @return true if unloading the font succeeded
  349. * @return false if unloading the font failed
  350. */
  351. bool qp_close_font(painter_font_handle_t font);
  352. /**
  353. * Measures the width (in pixels) of the supplied string, given the specified font.
  354. *
  355. * @param font[in] the handle of the font
  356. * @param str[in] the string to measure
  357. * @return the width (in pixels) needed to draw the specified string
  358. */
  359. int16_t qp_textwidth(painter_font_handle_t font, const char *str);
  360. /**
  361. * Draws text to the display.
  362. *
  363. * @param device[in] the handle of the device to control
  364. * @param x[in] the x-position where the text should be drawn onto the device
  365. * @param y[in] the y-position where the text should be drawn onto the device
  366. * @param font[in] the handle of the font
  367. * @param str[in] the string to draw
  368. * @return the width (in pixels) used when drawing the specified string
  369. */
  370. int16_t qp_drawtext(painter_device_t device, uint16_t x, uint16_t y, painter_font_handle_t font, const char *str);
  371. /**
  372. * Draws text to the display, recoloring monochrome fonts to the desired foreground/background.
  373. *
  374. * @param device[in] the handle of the device to control
  375. * @param x[in] the x-position where the text should be drawn onto the device
  376. * @param y[in] the y-position where the text should be drawn onto the device
  377. * @param font[in] the handle of the font
  378. * @param str[in] the string to draw
  379. * @param hue_fg[in] the foreground hue to use, with 0-360 mapped to 0-255
  380. * @param sat_fg[in] the foreground saturation to use, with 0-100% mapped to 0-255
  381. * @param val_fg[in] the foreground value to use, with 0-100% mapped to 0-255
  382. * @param hue_bg[in] the background hue to use, with 0-360 mapped to 0-255
  383. * @param sat_bg[in] the background saturation to use, with 0-100% mapped to 0-255
  384. * @param val_bg[in] the background value to use, with 0-100% mapped to 0-255
  385. * @return the width (in pixels) used when drawing the specified string
  386. */
  387. int16_t qp_drawtext_recolor(painter_device_t device, uint16_t x, uint16_t y, painter_font_handle_t font, const char *str, uint8_t hue_fg, uint8_t sat_fg, uint8_t val_fg, uint8_t hue_bg, uint8_t sat_bg, uint8_t val_bg);
  388. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  389. // Quantum Painter Drivers
  390. #ifdef QUANTUM_PAINTER_ILI9163_ENABLE
  391. # include "qp_ili9163.h"
  392. #endif // QUANTUM_PAINTER_ILI9163_ENABLE
  393. #ifdef QUANTUM_PAINTER_ILI9341_ENABLE
  394. # include "qp_ili9341.h"
  395. #endif // QUANTUM_PAINTER_ILI9341_ENABLE
  396. #ifdef QUANTUM_PAINTER_ST7789_ENABLE
  397. # include "qp_st7789.h"
  398. #endif // QUANTUM_PAINTER_ST7789_ENABLE
  399. #ifdef QUANTUM_PAINTER_GC9A01_ENABLE
  400. # include "qp_gc9a01.h"
  401. #endif // QUANTUM_PAINTER_GC9A01_ENABLE
  402. #ifdef QUANTUM_PAINTER_SSD1351_ENABLE
  403. # include "qp_ssd1351.h"
  404. #endif // QUANTUM_PAINTER_SSD1351_ENABLE