1 | /* ***** BEGIN LICENSE BLOCK ***** |
---|
2 | * Version: CDDL 1.0/LGPL 2.1 |
---|
3 | * |
---|
4 | * The contents of this file are subject to the COMMON DEVELOPMENT AND |
---|
5 | * DISTRIBUTION LICENSE (CDDL) Version 1.0 (the "License"); you may not use |
---|
6 | * this file except in compliance with the License. You may obtain a copy of |
---|
7 | * the License at http://www.sun.com/cddl/ |
---|
8 | * |
---|
9 | * Software distributed under the License is distributed on an "AS IS" basis, |
---|
10 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
---|
11 | * for the specific language governing rights and limitations under the |
---|
12 | * License. |
---|
13 | * |
---|
14 | * The Initial Developer of the Original Code is |
---|
15 | * Eugene Romanenko, netlabs.org. |
---|
16 | * Portions created by the Initial Developer are Copyright (C) 2006 |
---|
17 | * the Initial Developer. All Rights Reserved. |
---|
18 | * |
---|
19 | * Contributor(s): |
---|
20 | * |
---|
21 | * Alternatively, the contents of this file may be used under the terms of |
---|
22 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
---|
23 | * in which case the provisions of the LGPL are applicable instead of those |
---|
24 | * above. If you wish to allow use of your version of this file only under the |
---|
25 | * terms of the LGPL, and not to allow others to use your version of this file |
---|
26 | * under the terms of the CDDL, indicate your decision by deleting the |
---|
27 | * provisions above and replace them with the notice and other provisions |
---|
28 | * required by the LGPL. If you do not delete the provisions above, a recipient |
---|
29 | * may use your version of this file under the terms of any one of the CDDL |
---|
30 | * or the LGPL. |
---|
31 | * |
---|
32 | * ***** END LICENSE BLOCK ***** */ |
---|
33 | |
---|
34 | // interferes with os2medef.h |
---|
35 | #undef VERSION |
---|
36 | |
---|
37 | #define INCL_DOS |
---|
38 | #define INCL_MMIOOS2 |
---|
39 | #define INCL_GPI |
---|
40 | #include <os2.h> |
---|
41 | #include <os2me.h> |
---|
42 | #include <fourcc.h> |
---|
43 | |
---|
44 | #include <stdlib.h> |
---|
45 | #include <string.h> |
---|
46 | #include <io.h> |
---|
47 | #include <fcntl.h> |
---|
48 | |
---|
49 | #include <ludoc.xh> |
---|
50 | |
---|
51 | #include "Lucide.h" |
---|
52 | #include "luutils.h" |
---|
53 | |
---|
54 | #define LUTHUMB_SIZE_X 256 |
---|
55 | #define LUTHUMB_SIZE_Y 256 |
---|
56 | static const char * const LUTHUMB_EA_NAME = "LUCIDE_THUMBNAIL"; |
---|
57 | |
---|
58 | |
---|
59 | static bool loadMMIOFuncs(); |
---|
60 | |
---|
61 | static HMODULE mmioHndl = NULLHANDLE; |
---|
62 | static bool mmioFuncsLoaded = loadMMIOFuncs(); |
---|
63 | |
---|
64 | static void freeMmio() |
---|
65 | { |
---|
66 | if ( mmioHndl != NULLHANDLE ) { |
---|
67 | DosFreeModule( mmioHndl ); |
---|
68 | } |
---|
69 | } |
---|
70 | |
---|
71 | HMMIO APIENTRY (*pMmioOpen)(PSZ,PMMIOINFO,ULONG); |
---|
72 | LONG APIENTRY (*pMmioWrite)(HMMIO,PCHAR,LONG); |
---|
73 | ULONG APIENTRY (*pMmioSetHeader)(HMMIO,PVOID,LONG,PLONG,ULONG,ULONG); |
---|
74 | USHORT APIENTRY (*pMmioClose)(HMMIO,USHORT); |
---|
75 | ULONG APIENTRY (*pMmioIdentifyFile)(PSZ,PMMIOINFO,PMMFORMATINFO,PFOURCC,ULONG,ULONG); |
---|
76 | ULONG APIENTRY (*pMmioQueryHeaderLength)(HMMIO,PLONG,ULONG,ULONG); |
---|
77 | ULONG APIENTRY (*pMmioGetHeader)(HMMIO,PVOID,LONG,PLONG,ULONG,ULONG); |
---|
78 | LONG APIENTRY (*pMmioRead)(HMMIO,PCHAR,LONG); |
---|
79 | |
---|
80 | static bool loadMMIOFuncs() |
---|
81 | { |
---|
82 | bool res = false; |
---|
83 | do |
---|
84 | { |
---|
85 | if ( DosLoadModule( NULL, 0, "MMIO", &mmioHndl ) != 0 ) |
---|
86 | break; |
---|
87 | if ( DosQueryProcAddr( mmioHndl, 0, "mmioOpen", (PFN *)&pMmioOpen ) != 0 ) |
---|
88 | break; |
---|
89 | if ( DosQueryProcAddr( mmioHndl, 0, "mmioWrite", (PFN *)&pMmioWrite ) != 0 ) |
---|
90 | break; |
---|
91 | if ( DosQueryProcAddr( mmioHndl, 0, "mmioSetHeader", (PFN *)&pMmioSetHeader ) != 0 ) |
---|
92 | break; |
---|
93 | if ( DosQueryProcAddr( mmioHndl, 0, "mmioClose", (PFN *)&pMmioClose ) != 0 ) |
---|
94 | break; |
---|
95 | if ( DosQueryProcAddr( mmioHndl, 0, "mmioIdentifyFile", (PFN *)&pMmioIdentifyFile ) != 0 ) |
---|
96 | break; |
---|
97 | if ( DosQueryProcAddr( mmioHndl, 0, "mmioQueryHeaderLength", (PFN *)&pMmioQueryHeaderLength ) != 0 ) |
---|
98 | break; |
---|
99 | if ( DosQueryProcAddr( mmioHndl, 0, "mmioGetHeader", (PFN *)&pMmioGetHeader ) != 0 ) |
---|
100 | break; |
---|
101 | if ( DosQueryProcAddr( mmioHndl, 0, "mmioRead", (PFN *)&pMmioRead ) != 0 ) |
---|
102 | break; |
---|
103 | |
---|
104 | res = true; |
---|
105 | } while (0); |
---|
106 | |
---|
107 | atexit( freeMmio ); |
---|
108 | |
---|
109 | return res; |
---|
110 | } |
---|
111 | |
---|
112 | |
---|
113 | static bool saveToImage( char *pszFileName, char *format, |
---|
114 | ULONG width, ULONG height, ULONG row_size, |
---|
115 | ULONG bpp, char* src_buf ) |
---|
116 | { |
---|
117 | bool ret = false; |
---|
118 | MMIOINFO mmioinfoTarget; |
---|
119 | HMMIO hmmioTarget; |
---|
120 | PBYTE pbBuffer = NULL; |
---|
121 | ULONG cbBuffer,cbBitmapInfo, rl; |
---|
122 | ULONG rc; |
---|
123 | MMIMAGEHEADER mmImgHdr; |
---|
124 | BITMAPINFO2 bmp; |
---|
125 | FOURCC saveas; |
---|
126 | |
---|
127 | rl = ( ( bpp * width + 31 ) / 32 ) * 4; |
---|
128 | cbBuffer = rl * height; |
---|
129 | |
---|
130 | if ( !format ) { |
---|
131 | return ret; |
---|
132 | } |
---|
133 | |
---|
134 | saveas = mmioFOURCC( format[0], format[1], format[2], format[3] ); |
---|
135 | |
---|
136 | // fill bmp |
---|
137 | memset( &bmp, 0, sizeof( bmp ) ); |
---|
138 | bmp.cbFix = sizeof( bmp ); |
---|
139 | bmp.cx = width; |
---|
140 | bmp.cy = height; |
---|
141 | bmp.cPlanes = 1; |
---|
142 | bmp.cBitCount = bpp; |
---|
143 | bmp.ulCompression = 0; |
---|
144 | bmp.cbImage = cbBuffer; |
---|
145 | |
---|
146 | cbBitmapInfo = sizeof( bmp ); |
---|
147 | |
---|
148 | memset( &mmioinfoTarget, 0L, sizeof( MMIOINFO ) ); |
---|
149 | mmioinfoTarget.fccIOProc = saveas; |
---|
150 | mmioinfoTarget.ulTranslate = MMIO_TRANSLATEHEADER | MMIO_TRANSLATEDATA; |
---|
151 | hmmioTarget = pMmioOpen( pszFileName, &mmioinfoTarget, MMIO_CREATE | MMIO_WRITE | |
---|
152 | MMIO_DENYWRITE | MMIO_NOIDENTIFY ); |
---|
153 | if ( hmmioTarget ) |
---|
154 | { |
---|
155 | ULONG ulBytesWritten; |
---|
156 | |
---|
157 | memset( &mmImgHdr, 0, sizeof( MMIMAGEHEADER ) ); |
---|
158 | mmImgHdr.ulHeaderLength = sizeof(MMIMAGEHEADER); |
---|
159 | mmImgHdr.ulContentType = MMIO_IMAGE_UNKNOWN; |
---|
160 | mmImgHdr.ulMediaType = MMIO_MEDIATYPE_IMAGE; |
---|
161 | mmImgHdr.mmXDIBHeader.XDIBHeaderPrefix.ulMemSize = cbBuffer; |
---|
162 | mmImgHdr.mmXDIBHeader.XDIBHeaderPrefix.ulPelFormat = ( bpp < 24 ) ? |
---|
163 | mmioFOURCC('p','a','l','b') : mmioFOURCC('r','g','b','b'); |
---|
164 | |
---|
165 | mmImgHdr.mmXDIBHeader.XDIBHeaderPrefix.usTransType = 0; |
---|
166 | mmImgHdr.mmXDIBHeader.XDIBHeaderPrefix.ulTransVal = 0; |
---|
167 | memcpy( &mmImgHdr.mmXDIBHeader.BMPInfoHeader2, &bmp, cbBitmapInfo ); |
---|
168 | rc = pMmioSetHeader( hmmioTarget, &mmImgHdr, sizeof(MMIMAGEHEADER), |
---|
169 | (PLONG)&ulBytesWritten, 0L, 0L); |
---|
170 | if ( rc == MMIO_SUCCESS ) |
---|
171 | { |
---|
172 | for ( int k=0; k < height; k++ ) |
---|
173 | { |
---|
174 | char *line = src_buf + ( k * row_size ); |
---|
175 | |
---|
176 | ulBytesWritten = pMmioWrite( hmmioTarget, (char*)line, rl ); |
---|
177 | |
---|
178 | if ( ( ulBytesWritten == MMIO_ERROR ) || ( ulBytesWritten == 0 ) ) { |
---|
179 | break; |
---|
180 | } |
---|
181 | } |
---|
182 | |
---|
183 | if ( ( ulBytesWritten != MMIO_ERROR ) && ( ulBytesWritten != 0 ) ) { |
---|
184 | ret = true; |
---|
185 | } |
---|
186 | } |
---|
187 | |
---|
188 | pMmioClose( hmmioTarget, 0L ); |
---|
189 | } |
---|
190 | |
---|
191 | return ret; |
---|
192 | } |
---|
193 | |
---|
194 | static BOOL set_ea( const char *file_name, const char *ea_name, |
---|
195 | const char *ea_data, int ea_data_len ) |
---|
196 | { |
---|
197 | APIRET rc = 0; |
---|
198 | EAOP2 op; |
---|
199 | |
---|
200 | char *databuf = new char[(64*2*1024)+1024]; // twice 64K for EA data + 1024 for any case |
---|
201 | |
---|
202 | op.fpGEA2List = (PGEA2LIST)0; |
---|
203 | op.fpFEA2List = (PFEA2LIST)databuf; |
---|
204 | |
---|
205 | int ea_name_len = strlen( ea_name ); |
---|
206 | if ( ea_name_len > 255 ) { |
---|
207 | delete databuf; |
---|
208 | return FALSE; |
---|
209 | } |
---|
210 | |
---|
211 | char *databufp = databuf + sizeof( long ); |
---|
212 | *((long*)databufp) = 0; // Next field offset is zero - just one field here |
---|
213 | databufp += sizeof(long); |
---|
214 | *databufp++ = 0; // not critical |
---|
215 | *databufp++ = (char)ea_name_len; |
---|
216 | *((short*)databufp) = (short)ea_data_len; |
---|
217 | databufp += sizeof(short); |
---|
218 | memcpy( databufp, ea_name, ea_name_len+1 ); // with trailing zero |
---|
219 | databufp += ea_name_len+1; |
---|
220 | memcpy( databufp, ea_data, ea_data_len ); // with trailing zero |
---|
221 | databufp += ea_data_len; |
---|
222 | |
---|
223 | *((long*)databuf) = databufp-databuf; // Size of all that stuff |
---|
224 | |
---|
225 | // HPFS386 workaround |
---|
226 | // Save timestamp (setting EA drops timestamp on HPFS386) |
---|
227 | APIRET qpirc = 0; |
---|
228 | FILESTATUS3 fs = { 0 }; |
---|
229 | qpirc = DosQueryPathInfo( file_name, FIL_STANDARD, &fs, sizeof( fs ) ); |
---|
230 | |
---|
231 | // Write EA |
---|
232 | rc = DosSetPathInfo( file_name, FIL_QUERYEASIZE, &op, sizeof(op), 0); |
---|
233 | delete databuf; |
---|
234 | |
---|
235 | // Restore timestamp |
---|
236 | if ( qpirc == 0 ) { |
---|
237 | DosSetPathInfo( file_name, FIL_STANDARD, &fs, sizeof( fs ), DSPI_WRTTHRU ); |
---|
238 | } |
---|
239 | |
---|
240 | if ( rc != 0 ) { |
---|
241 | return FALSE; |
---|
242 | } |
---|
243 | |
---|
244 | return TRUE; |
---|
245 | } |
---|
246 | |
---|
247 | bool Lucide::isThumbNeeded( const char *fn ) |
---|
248 | { |
---|
249 | // First, check if mmio is available |
---|
250 | if ( !mmioFuncsLoaded ) { |
---|
251 | return false; |
---|
252 | } |
---|
253 | |
---|
254 | // Second, check if file is writeable |
---|
255 | if ( access( fn, W_OK ) != 0 ) { |
---|
256 | // Isn't writable, do not waste time to render thumbnail |
---|
257 | return false; |
---|
258 | } |
---|
259 | |
---|
260 | // Third, check if thumbnail EA already present |
---|
261 | UCHAR EnumBuf[200] = {0}; // Data Buffer |
---|
262 | ULONG ulEnumCnt = 0; // Count of entries to return |
---|
263 | FEA2 *ptr = NULL; // Pointer to data items returned |
---|
264 | ULONG ulTemp = 0; |
---|
265 | APIRET rc = 0; |
---|
266 | |
---|
267 | ulEnumCnt = (ULONG)-1; // Request as many attributes as will fit in buffer |
---|
268 | |
---|
269 | rc = DosEnumAttribute( ENUMEA_REFTYPE_PATH, (PVOID)fn, 1L, &EnumBuf, sizeof( EnumBuf ), |
---|
270 | &ulEnumCnt, ENUMEA_LEVEL_NO_VALUE ); |
---|
271 | |
---|
272 | if ( rc != 0 ) { |
---|
273 | // error look for EA names, return 'false' to prevent EA creation |
---|
274 | // as if enum failed, creation may also fail |
---|
275 | return false; |
---|
276 | } |
---|
277 | |
---|
278 | ptr = (FEA2 *)EnumBuf; // Mask the buffer pointer to an FEA2 structure |
---|
279 | |
---|
280 | for ( ULONG i = 0; i < ulEnumCnt; i++ ) |
---|
281 | { |
---|
282 | if ( strcmp( ptr->szName, LUTHUMB_EA_NAME ) == 0 ) { |
---|
283 | return false; // Thumbnail already present |
---|
284 | } |
---|
285 | /// increment the ptr with the value in oNextEntryOffset |
---|
286 | ulTemp = ptr->oNextEntryOffset + (ULONG)ptr; |
---|
287 | ptr = (FEA2 *)ulTemp; |
---|
288 | } |
---|
289 | return true; |
---|
290 | } |
---|
291 | |
---|
292 | |
---|
293 | void Lucide::createThumbnail( LuDocument *doc ) |
---|
294 | { |
---|
295 | if ( !doc->isScalable( ev ) ) { |
---|
296 | return; |
---|
297 | } |
---|
298 | |
---|
299 | // render first page |
---|
300 | double width = 0, height = 0; |
---|
301 | doc->getPageSize( ev, 0, &width, &height ); |
---|
302 | double zoom = __min( (double)LUTHUMB_SIZE_X / width, (double)LUTHUMB_SIZE_Y / height ); |
---|
303 | short bpp = doc->getBpp( ev ); |
---|
304 | |
---|
305 | long rx = width * zoom; |
---|
306 | long ry = height * zoom; |
---|
307 | LuPixbuf *pixbuf = new LuPixbuf( ev, rx, ry, bpp ); |
---|
308 | if ( !doc->renderPageToPixbuf( ev, 0, 0, 0, rx, ry, zoom, 0, pixbuf, NULL, NULL ) ) { |
---|
309 | delete pixbuf; |
---|
310 | return; |
---|
311 | } |
---|
312 | |
---|
313 | char *tmpgif = new char[ CCHMAXPATH ]; |
---|
314 | getTmpDir( tmpgif ); |
---|
315 | strcat( tmpgif, "LUTHUMB.TMP" ); |
---|
316 | |
---|
317 | bool saved = saveToImage( tmpgif, "GIFC", rx, ry, pixbuf->getRowSize( ev ), |
---|
318 | bpp * 8, (char *)pixbuf->getDataPtr( ev ) ); |
---|
319 | delete pixbuf; |
---|
320 | if ( saved ) |
---|
321 | { |
---|
322 | // If image file saved, read file content into |
---|
323 | // thumbnailData buffer, to be able write it into EA |
---|
324 | // when document will be closed |
---|
325 | int h = open( tmpgif, O_RDONLY | O_BINARY | O_NOINHERIT ); |
---|
326 | if ( h != -1 ) |
---|
327 | { |
---|
328 | long flen = filelength( h ); |
---|
329 | if ( flen > 0 ) |
---|
330 | { |
---|
331 | thumbnailData = new char[ flen ]; |
---|
332 | thumbnailDataLen = flen; |
---|
333 | if ( read( h, thumbnailData, flen ) != flen ) { |
---|
334 | delete thumbnailData; |
---|
335 | thumbnailData = NULL; |
---|
336 | thumbnailDataLen = 0; |
---|
337 | } |
---|
338 | } |
---|
339 | close( h ); |
---|
340 | } |
---|
341 | } |
---|
342 | // if tmp file exist - delete it |
---|
343 | if ( access( tmpgif, F_OK ) == 0 ) { |
---|
344 | unlink( tmpgif ); |
---|
345 | } |
---|
346 | delete tmpgif; |
---|
347 | } |
---|
348 | |
---|
349 | void Lucide::writeThumbnail( const char *fn ) |
---|
350 | { |
---|
351 | if ( ( thumbnailData == NULL ) || ( thumbnailDataLen == 0 ) ) { |
---|
352 | return; |
---|
353 | } |
---|
354 | |
---|
355 | set_ea( fn, LUTHUMB_EA_NAME, (const char *)thumbnailData, thumbnailDataLen ); |
---|
356 | delete thumbnailData; |
---|
357 | thumbnailData = NULL; |
---|
358 | thumbnailDataLen = 0; |
---|
359 | } |
---|
360 | |
---|
361 | |
---|
362 | HBITMAP LoadBitmap( HAB hab, HDC hdc, HPS *hps, PSZ pszFileName ) |
---|
363 | { |
---|
364 | HBITMAP hbm; |
---|
365 | MMIOINFO mmioinfo; |
---|
366 | MMFORMATINFO mmFormatInfo; |
---|
367 | HMMIO hmmio; |
---|
368 | ULONG ulImageHeaderLength; |
---|
369 | MMIMAGEHEADER mmImgHdr; |
---|
370 | ULONG ulBytesRead; |
---|
371 | ULONG dwNumRowBytes; |
---|
372 | PBYTE pRowBuffer; |
---|
373 | ULONG dwRowCount; |
---|
374 | SIZEL ImageSize; |
---|
375 | ULONG dwHeight, dwWidth; |
---|
376 | SHORT wBitCount; |
---|
377 | FOURCC fccStorageSystem; |
---|
378 | ULONG dwPadBytes; |
---|
379 | ULONG dwRowBits; |
---|
380 | ULONG ulReturnCode; |
---|
381 | ULONG dwReturnCode; |
---|
382 | HBITMAP hbReturnCode; |
---|
383 | LONG lReturnCode; |
---|
384 | FOURCC fccIOProc; |
---|
385 | |
---|
386 | |
---|
387 | ulReturnCode = pMmioIdentifyFile( pszFileName, 0L, &mmFormatInfo, |
---|
388 | &fccStorageSystem, 0L, 0L ); |
---|
389 | if ( ulReturnCode == MMIO_ERROR ) { |
---|
390 | return NULLHANDLE; |
---|
391 | } |
---|
392 | |
---|
393 | if( mmFormatInfo.fccIOProc == FOURCC_DOS ) { |
---|
394 | return NULLHANDLE; |
---|
395 | } |
---|
396 | |
---|
397 | if ( (mmFormatInfo.ulMediaType != MMIO_MEDIATYPE_IMAGE) || |
---|
398 | ((mmFormatInfo.ulFlags & MMIO_CANREADTRANSLATED) == 0) ) { |
---|
399 | return NULLHANDLE; |
---|
400 | } |
---|
401 | else { |
---|
402 | fccIOProc = mmFormatInfo.fccIOProc; |
---|
403 | } |
---|
404 | |
---|
405 | memset( &mmioinfo, 0L, sizeof( MMIOINFO ) ); |
---|
406 | mmioinfo.fccIOProc = fccIOProc; |
---|
407 | mmioinfo.ulTranslate = MMIO_TRANSLATEHEADER | MMIO_TRANSLATEDATA; |
---|
408 | |
---|
409 | hmmio = pMmioOpen( (PSZ)pszFileName, &mmioinfo, |
---|
410 | MMIO_READ | MMIO_DENYWRITE | MMIO_NOIDENTIFY ); |
---|
411 | |
---|
412 | if ( !hmmio ) { |
---|
413 | return NULLHANDLE; |
---|
414 | } |
---|
415 | |
---|
416 | dwReturnCode = pMmioQueryHeaderLength( hmmio, (PLONG)&ulImageHeaderLength, 0L, 0L ); |
---|
417 | |
---|
418 | if ( ulImageHeaderLength != sizeof ( MMIMAGEHEADER ) ) { |
---|
419 | pMmioClose( hmmio, 0L ); |
---|
420 | return NULLHANDLE; |
---|
421 | } |
---|
422 | |
---|
423 | ulReturnCode = pMmioGetHeader( hmmio, &mmImgHdr, sizeof( MMIMAGEHEADER ), |
---|
424 | (PLONG)&ulBytesRead, 0L, 0L ); |
---|
425 | |
---|
426 | if ( ulReturnCode != MMIO_SUCCESS ) { |
---|
427 | pMmioClose( hmmio, 0L ); |
---|
428 | return NULLHANDLE; |
---|
429 | } |
---|
430 | |
---|
431 | dwHeight = mmImgHdr.mmXDIBHeader.BMPInfoHeader2.cy; |
---|
432 | dwWidth = mmImgHdr.mmXDIBHeader.BMPInfoHeader2.cx; |
---|
433 | wBitCount = mmImgHdr.mmXDIBHeader.BMPInfoHeader2.cBitCount; |
---|
434 | dwRowBits = dwWidth * mmImgHdr.mmXDIBHeader.BMPInfoHeader2.cBitCount; |
---|
435 | dwNumRowBytes = dwRowBits >> 3; |
---|
436 | |
---|
437 | if ( dwRowBits % 8 ) { |
---|
438 | dwNumRowBytes++; |
---|
439 | } |
---|
440 | |
---|
441 | dwPadBytes = ( dwNumRowBytes % 4 ); |
---|
442 | |
---|
443 | if ( dwPadBytes ) { |
---|
444 | dwNumRowBytes += 4 - dwPadBytes; |
---|
445 | } |
---|
446 | |
---|
447 | pRowBuffer = (PBYTE)malloc( dwNumRowBytes ); |
---|
448 | |
---|
449 | ImageSize.cx = dwWidth; |
---|
450 | ImageSize.cy = dwHeight; |
---|
451 | |
---|
452 | *hps = GpiCreatePS( hab, hdc, &ImageSize, |
---|
453 | PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC ); |
---|
454 | |
---|
455 | if ( !*hps ) { |
---|
456 | free( pRowBuffer ); |
---|
457 | pMmioClose( hmmio, 0L ); |
---|
458 | return NULLHANDLE; |
---|
459 | } |
---|
460 | |
---|
461 | hbm = GpiCreateBitmap( *hps, &mmImgHdr.mmXDIBHeader.BMPInfoHeader2, 0L, NULL, NULL ); |
---|
462 | |
---|
463 | if ( !hbm ) |
---|
464 | { |
---|
465 | free( pRowBuffer ); |
---|
466 | pMmioClose( hmmio, 0L ); |
---|
467 | return NULLHANDLE; |
---|
468 | } |
---|
469 | |
---|
470 | hbReturnCode = GpiSetBitmap( *hps, hbm ); |
---|
471 | |
---|
472 | for ( dwRowCount = 0; dwRowCount < dwHeight; dwRowCount++ ) |
---|
473 | { |
---|
474 | ulBytesRead = pMmioRead( hmmio, pRowBuffer, dwNumRowBytes ); |
---|
475 | |
---|
476 | if ( !ulBytesRead ) { |
---|
477 | break; |
---|
478 | } |
---|
479 | |
---|
480 | lReturnCode = GpiSetBitmapBits( *hps, dwRowCount, 1, pRowBuffer, |
---|
481 | (PBITMAPINFO2)&mmImgHdr.mmXDIBHeader.BMPInfoHeader2 ); |
---|
482 | } |
---|
483 | |
---|
484 | pMmioClose( hmmio, 0L ); |
---|
485 | free( pRowBuffer ); |
---|
486 | |
---|
487 | return hbm; |
---|
488 | } |
---|
489 | |
---|