version 2.8
gwin_image.c
Go to the documentation of this file.
1 /*
2  * This file is subject to the terms of the GFX License. If a copy of
3  * the license was not distributed with this file, you can obtain one at:
4  *
5  * http://ugfx.org/license.html
6  */
7 
8 /**
9  * @file src/gwin/gwin_image.c
10  * @brief GWIN sub-system image code
11  */
12 
13 #include "../../gfx.h"
14 
15 #if GFX_USE_GWIN && GWIN_NEED_IMAGE
16 
17 #include "gwin_class.h"
18 
19 #define gw ((GImageObject *)gh)
20 
21 static void ImageDestroy(GWindowObject *gh) {
22  // Stop the timer
23  #if GWIN_NEED_IMAGE_ANIMATION
24  gtimerStop(&gw->timer);
25  #endif
26  if (gdispImageIsOpen(&gw->image))
27  gdispImageClose(&gw->image);
28 }
29 
30 #if GWIN_NEED_IMAGE_ANIMATION
31  static void ImageTimer(void *param) {
32  _gwinUpdate((GHandle)param);
33  }
34 #endif
35 
36 static void ImageRedraw(GHandle gh) {
37  coord_t x, y, w, h, dx, dy;
38  color_t bg;
39  #if GWIN_NEED_IMAGE_ANIMATION
40  delaytime_t delay;
41  #endif
42 
43  // The default display area
44  dx = 0;
45  dy = 0;
46  x = gh->x;
47  y = gh->y;
48  w = gh->width;
49  h = gh->height;
50  bg = gwinGetDefaultBgColor();
51 
52  // If the image isn't open just clear the area
53  if (!gdispImageIsOpen(&gw->image)) {
54  gdispGFillArea(gh->display, x, y, w, h, bg);
55  return;
56  }
57 
58  // Center horizontally if the area is larger than the image
59  if (gw->image.width < w) {
60  w = gw->image.width;
61  dx = (gh->width-w)/2;
62  x += dx;
63  if (dx)
64  gdispGFillArea(gh->display, gh->x, y, dx, h, bg);
65  gdispGFillArea(gh->display, x+w, y, gh->width-dx-w, h, bg);
66  dx = 0;
67  }
68 
69  // Center image horizontally if the area is smaller than the image
70  else if (gw->image.width > w) {
71  dx = (gw->image.width - w)/2;
72  }
73 
74  // Center vertically if the area is larger than the image
75  if (gw->image.height < h) {
76  h = gw->image.height;
77  dy = (gh->height-h)/2;
78  y += dy;
79  if (dy)
80  gdispGFillArea(gh->display, x, gh->y, w, dy, bg);
81  gdispGFillArea(gh->display, x, y+h, w, gh->height-dy-h, bg);
82  dy = 0;
83  }
84 
85  // Center image vertically if the area is smaller than the image
86  else if (gw->image.height > h) {
87  dy = (gw->image.height - h)/2;
88  }
89 
90  // Reset the background color in case it has changed
91  gdispImageSetBgColor(&gw->image, bg);
92 
93  // Display the image
94  gdispGImageDraw(gh->display, &gw->image, x, y, w, h, dx, dy);
95 
96  #if GWIN_NEED_IMAGE_ANIMATION
97  // read the delay for the next frame
98  delay = gdispImageNext(&gw->image);
99 
100  // Wait for that delay if required
101  switch(delay) {
102  case TIME_INFINITE:
103  // Everything is done
104  break;
105  case TIME_IMMEDIATE:
106  // We can't allow a continuous loop here as it would lock the system up so we delay for the minimum period
107  delay = 1;
108  // Fall through
109  default:
110  // Start the timer to draw the next frame of the animation
111  gtimerStart(&gw->timer, ImageTimer, (void*)gh, FALSE, delay);
112  break;
113  }
114  #endif
115 }
116 
117 static const gwinVMT imageVMT = {
118  "Image", // The class name
119  sizeof(GImageObject), // The object size
120  ImageDestroy, // The destroy routine
121  ImageRedraw, // The redraw routine
122  0, // The after-clear routine
123 };
124 
125 GHandle gwinGImageCreate(GDisplay *g, GImageObject *gobj, GWindowInit *pInit) {
126  if (!(gobj = (GImageObject *)_gwindowCreate(g, &gobj->g, pInit, &imageVMT, 0)))
127  return 0;
128 
129  // Ensure the gdispImageIsOpen() gives valid results
130  gdispImageInit(&gobj->image);
131 
132  // Initialise the timer
133  #if GWIN_NEED_IMAGE_ANIMATION
134  gtimerInit(&gobj->timer);
135  #endif
136 
137  gwinSetVisible((GHandle)gobj, pInit->show);
138 
139  return (GHandle)gobj;
140 }
141 
142 bool_t gwinImageOpenGFile(GHandle gh, GFILE *f) {
143  // is it a valid handle?
144  if (gh->vmt != (gwinVMT *)&imageVMT)
145  return FALSE;
146 
147  if (gdispImageIsOpen(&gw->image))
148  gdispImageClose(&gw->image);
149 
150  if ((gdispImageOpenGFile(&gw->image, f) & GDISP_IMAGE_ERR_UNRECOVERABLE))
151  return FALSE;
152 
153  _gwinUpdate(gh);
154 
155  return TRUE;
156 }
157 
159  // is it a valid handle?
160  if (gh->vmt != (gwinVMT *)&imageVMT)
161  return GDISP_IMAGE_ERR_BADFORMAT;
162 
163  return gdispImageCache(&gw->image);
164 }
165 
166 #undef gw
167 #endif // GFX_USE_GWIN && GWIN_NEED_IMAGE
delaytime_t gdispImageNext(gdispImage *img)
Prepare for the next frame/page in the image file.
const struct gwinVMT * vmt
Definition: gwin.h:45
The structure to initialise a GWIN.
Definition: gwin.h:75
void gtimerInit(GTimer *pt)
Initialise a timer.
Definition: gtimer.c:129
bool_t gdispImageIsOpen(gdispImage *img)
Is an image open.
int16_t coord_t
The type for a coordinate or length on the screen.
Definition: gdisp.h:39
coord_t y
Definition: gwin.h:48
coord_t x
Definition: gwin.h:47
void gdispImageClose(gdispImage *img)
Close an image and release any dynamically allocated working storage.
void gtimerStop(GTimer *pt)
Stop a timer (periodic or otherwise)
Definition: gtimer.c:190
struct GFILE GFILE
A file pointer.
Definition: gfile.h:34
#define FALSE
Generic &#39;false&#39; boolean constant.
Definition: gfx.h:31
gdispImageError gdispImageCache(gdispImage *img)
Cache the image.
void gdispGFillArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color)
Fill an area with a color.
gdispImageError gwinImageCache(GHandle gh)
Cache the image.
void gwinSetVisible(GHandle gh, bool_t visible)
Sets whether a window is visible or not.
color_t gwinGetDefaultBgColor(void)
Get the default background color for all new GWIN windows.
bool_t show
Definition: gwin.h:80
GDisplay * display
Definition: gwin.h:46
void gdispImageSetBgColor(gdispImage *img, color_t bgcolor)
Set the background color of the image.
coord_t height
Definition: gwin.h:50
void gtimerStart(GTimer *pt, GTimerFunction fn, void *param, bool_t periodic, delaytime_t millisec)
Set a timer going or alter its properties if it is already going.
Definition: gtimer.c:139
coord_t width
Definition: gwin.h:49
GHandle gwinGImageCreate(GDisplay *g, GImageObject *widget, GWindowInit *pInit)
Create an image widget.
gdispImageError gdispGImageDraw(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy)
Draw the image.
The Virtual Method Table for a GWIN window.
Definition: gwin_class.h:55
A window object structure.
Definition: gwin.h:40
bool_t gwinImageOpenGFile(GHandle gh, GFILE *f)
Opens the image using a GFILE.
COLOR_TYPE color_t
The color type definition.
Definition: gdisp_colors.h:412
void gdispImageInit(gdispImage *img)
Initialise a gdispImage object.
uint16_t gdispImageError
An image error code.
Definition: gdisp_image.h:37
#define TRUE
Generic &#39;true&#39; boolean constant.
Definition: gfx.h:38
gdispImageError gdispImageOpenGFile(gdispImage *img, GFILE *f)
Open an image using an open GFILE and get it ready for drawing.