µGFX  2.9
version 2.9
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.io/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  gCoord x, y, w, h, dx, dy;
38  gColor bg;
39  #if GWIN_NEED_IMAGE_ANIMATION
40  gDelay 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 gDelayForever:
103  // Everything is done
104  break;
105  case gDelayNone:
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, gFalse, 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 gBool gwinImageOpenGFile(GHandle gh, GFILE *f) {
143  // is it a valid handle?
144  if (gh->vmt != (gwinVMT *)&imageVMT)
145  return gFalse;
146 
147  if (gdispImageIsOpen(&gw->image))
148  gdispImageClose(&gw->image);
149 
150  if ((gdispImageOpenGFile(&gw->image, f) & GDISP_IMAGE_ERR_UNRECOVERABLE))
151  return gFalse;
152 
153  _gwinUpdate(gh);
154 
155  return gTrue;
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
COLOR_TYPE gColor
The color type definition.
Definition: gdisp_colors.h:437
void gdispGFillArea(GDisplay *g, gCoord x, gCoord y, gCoord cx, gCoord cy, gColor color)
Fill an area with a color.
gI16 gCoord
The type for a coordinate or length on the screen.
Definition: gdisp.h:39
struct GFILE GFILE
A file pointer.
Definition: gfile.h:34
void gtimerStart(GTimer *pt, GTimerFunction fn, void *param, gBool periodic, gDelay millisec)
Set a timer going or alter its properties if it is already going.
Definition: gtimer.c:139
void gtimerInit(GTimer *pt)
Initialise a timer.
Definition: gtimer.c:129
void gtimerStop(GTimer *pt)
Stop a timer (periodic or otherwise)
Definition: gtimer.c:190
gdispImageError gwinImageCache(GHandle gh)
Cache the image.
GHandle gwinGImageCreate(GDisplay *g, GImageObject *widget, GWindowInit *pInit)
Create an image widget.
gBool gwinImageOpenGFile(GHandle gh, GFILE *f)
Opens the image using a GFILE.
gdispImageError gdispImageCache(gImage *img)
Cache the image.
gdispImageError gdispImageOpenGFile(gImage *img, GFILE *f)
Open an image using an open GFILE and get it ready for drawing.
gdispImageError gdispGImageDraw(GDisplay *g, gImage *img, gCoord x, gCoord y, gCoord cx, gCoord cy, gCoord sx, gCoord sy)
Draw the image.
void gdispImageInit(gImage *img)
Initialise a gImage object.
gU16 gdispImageError
An image error code.
Definition: gdisp_image.h:37
gDelay gdispImageNext(gImage *img)
Prepare for the next frame/page in the image file.
gBool gdispImageIsOpen(gImage *img)
Is an image open.
void gdispImageClose(gImage *img)
Close an image and release any dynamically allocated working storage.
void gdispImageSetBgColor(gImage *img, gColor bgcolor)
Set the background color of the image.
void gwinSetVisible(GHandle gh, gBool visible)
Sets whether a window is visible or not.
gColor gwinGetDefaultBgColor(void)
Get the default background color for all new GWIN windows.
The structure to initialise a GWIN.
Definition: gwin.h:75
gBool show
Definition: gwin.h:80
A window object structure.
Definition: gwin.h:40
GDisplay * display
Definition: gwin.h:46
gCoord x
Definition: gwin.h:47
gCoord width
Definition: gwin.h:49
const struct gwinVMT * vmt
Definition: gwin.h:45
gCoord y
Definition: gwin.h:48
gCoord height
Definition: gwin.h:50
The Virtual Method Table for a GWIN window.
Definition: gwin_class.h:55