1 #include "win32\win32guts.h"
2 #ifndef _APRICOT_H_
3 #include "apricot.h"
4 #endif
5 #include "img_conv.h"
6 #include "guts.h"
7 #include "Window.h"
8 #include "Icon.h"
9 #include "DeviceBitmap.h"
10
11 #ifdef __cplusplus
12 extern "C" {
13 #endif
14
15
16 #define sys (( PDrawableData)(( PComponent) self)-> sysData)->
17 #define dsys( view) (( PDrawableData)(( PComponent) view)-> sysData)->
18 #define var (( PWidget) self)->
19 #define HANDLE sys handle
20 #define DHANDLE(x) dsys(x) handle
21
22 static int
image_guess_bitmap_type(Handle self)23 image_guess_bitmap_type( Handle self )
24 {
25 if ( is_apt( aptIcon ) && PIcon(self)-> maskType == imbpp8 )
26 return BM_LAYERED;
27 else if ( PImage( self)-> type == imBW)
28 return BM_BITMAP;
29 else
30 return BM_PIXMAP;
31 }
32
33
34 BITMAPINFO *
image_fill_bitmap_info(Handle self,XBITMAPINFO * bi,int bm_type)35 image_fill_bitmap_info( Handle self, XBITMAPINFO * bi, int bm_type)
36 {
37 int i;
38 PImage image = ( PImage) self;
39 int colors, depth;
40
41 if ( bm_type == BM_AUTO )
42 bm_type = image_guess_bitmap_type( self );
43
44 switch (bm_type) {
45 case BM_BITMAP:
46 depth = 1;
47 colors = 2;
48 break;
49 case BM_PIXMAP:
50 depth = image-> type & imBPP;
51 colors = (1 << depth) & 0x1ff;
52 break;
53 case BM_LAYERED:
54 colors = 0;
55 depth = 32;
56 break;
57 default:
58 warn("panic: bad use of image_fill_bitmap_info(%d)", bm_type);
59 return NULL;
60 }
61
62 if ( image-> type & ( imSignedInt | imRealNumber | imComplexNumber | imTrigComplexNumber)) {
63 warn("panic: image_fill_bitmap_info called on incompatible image");
64 return NULL;
65 }
66
67 if ( colors > image-> palSize) colors = image-> palSize;
68 memset( bi, 0, sizeof( BITMAPINFOHEADER) + colors * sizeof( RGBQUAD));
69 bi-> bmiHeader. biSize = sizeof( BITMAPINFOHEADER);
70 bi-> bmiHeader. biWidth = image-> w;
71 bi-> bmiHeader. biHeight = image-> h;
72 bi-> bmiHeader. biPlanes = 1;
73 bi-> bmiHeader. biBitCount = depth;
74 bi-> bmiHeader. biCompression = BI_RGB;
75 bi-> bmiHeader. biClrUsed = colors;
76 bi-> bmiHeader. biClrImportant = colors;
77
78 for ( i = 0; i < colors; i++) {
79 bi-> bmiColors[ i]. rgbRed = image-> palette[ i]. r;
80 bi-> bmiColors[ i]. rgbGreen = image-> palette[ i]. g;
81 bi-> bmiColors[ i]. rgbBlue = image-> palette[ i]. b;
82 }
83
84 return ( BITMAPINFO *) bi;
85 }
86
87 HPALETTE
image_create_palette(Handle self)88 image_create_palette( Handle self)
89 {
90 PDrawable i = ( PDrawable) self;
91 int j, nColors = i-> palSize;
92 XLOGPALETTE lp;
93 HPALETTE r;
94 RGBColor dest[ 256];
95 PRGBColor logp = i-> palette;
96
97 lp. palVersion = 0x300;
98 lp. palNumEntries = nColors;
99
100 if ( nColors == 0) return NULL;
101 if ( is_apt(aptImage) && PImage(self)->type == imRGB) return NULL;
102
103 if ( !sys p256) {
104 if ( nColors > 256) {
105 sys p256 = ( PXLOGPALETTE) malloc( sizeof( XLOGPALETTE));
106 cm_squeeze_palette( i-> palette, nColors, dest, 256);
107 nColors = lp. palNumEntries = 256;
108 logp = dest;
109 }
110
111 for ( j = 0; j < nColors; j++) {
112 lp. palPalEntry[ j]. peRed = logp[ j]. r;
113 lp. palPalEntry[ j]. peGreen = logp[ j]. g;
114 lp. palPalEntry[ j]. peBlue = logp[ j]. b;
115 lp. palPalEntry[ j]. peFlags = 0;
116 }
117
118 if ( sys p256)
119 memcpy( sys p256, &lp, sizeof( XLOGPALETTE));
120 if ( !( r = CreatePalette(( LOGPALETTE*) &lp))) apiErrRet;
121 } else {
122 if ( !( r = CreatePalette(( LOGPALETTE*) sys p256))) apiErrRet;
123 }
124 return r;
125 }
126
127 static Bool
icon2argb(PIcon i,uint32_t * argb_bits)128 icon2argb( PIcon i, uint32_t * argb_bits)
129 {
130 Byte * rgb_bits, *a_bits, *mask;
131 int y, maskLineSize, free_mask;
132
133 if ( i-> maskType != imbpp8 ) {
134 free_mask = true;
135 maskLineSize = LINE_SIZE(i->w, imbpp8);
136 mask = i->self->convert_mask(( Handle ) i, imbpp8 );
137 if ( !mask )
138 return false;
139 } else {
140 free_mask = false;
141 mask = i-> mask;
142 maskLineSize = i-> maskLine;
143 }
144
145 for (
146 y = 0,
147 rgb_bits = i->data,
148 a_bits = mask;
149 y < i->h;
150 y++,
151 rgb_bits += i-> lineSize,
152 a_bits += maskLineSize,
153 argb_bits += i-> w
154 ) {
155 register Byte *rgb_ptr = rgb_bits, *a_ptr = a_bits, *argb_ptr = (Byte*) argb_bits;
156 register int x = i->w;
157 for ( ; x > 0; x--) {
158 *argb_ptr++ = *rgb_ptr++;
159 *argb_ptr++ = *rgb_ptr++;
160 *argb_ptr++ = *rgb_ptr++;
161 *argb_ptr++ = *a_ptr++;
162 }
163 }
164
165 if ( free_mask ) free(mask);
166 return true;
167 }
168
169 static HBITMAP
image_create_argb_bitmap(Handle self,uint32_t ** argb_bits_ptr)170 image_create_argb_bitmap( Handle self, uint32_t ** argb_bits_ptr )
171 {
172 HBITMAP bm;
173 XBITMAPINFO xbi;
174 BITMAPINFO * bi;
175 HDC dc, compat_dc;
176 PIcon i = (PIcon) self;
177 uint32_t * argb_bits;
178
179 if ( !is_apt(aptIcon)) {
180 warn("panic: image_create_argb_bitmap called on a non-icon");
181 return NULL;
182 }
183
184 if (i-> type != imRGB ) {
185 HBITMAP ret;
186 Handle dup = CImage(self)->dup(self);
187 CImage(dup)->set_type(dup, imRGB);
188 ret = image_create_argb_bitmap( dup, argb_bits_ptr );
189 Object_destroy(dup);
190 return ret;
191 }
192
193 if ( argb_bits_ptr == NULL )
194 argb_bits_ptr = &argb_bits;
195
196 bm = NULL;
197
198 bi = image_fill_bitmap_info( self, &xbi, BM_LAYERED);
199 if ( !bi)
200 return NULL;
201
202 dc = GetDC(NULL);
203 compat_dc = CreateCompatibleDC(dc);
204
205 bi-> bmiHeader. biBitCount = 32;
206 bi-> bmiHeader. biSizeImage = bi->bmiHeader.biWidth * bi->bmiHeader. biHeight * 4;
207 bm = CreateDIBSection(compat_dc, bi, DIB_RGB_COLORS,
208 (LPVOID*) argb_bits_ptr, NULL, 0x0);
209 if (!bm) {
210 apiErr;
211 goto EXIT;
212 }
213
214 if ( !icon2argb(i, *argb_bits_ptr)) {
215 DeleteObject(bm);
216 bm = NULL;
217 }
218
219 EXIT:
220 DeleteDC( compat_dc);
221 ReleaseDC( NULL, dc);
222 return bm;
223 }
224
225
226 HBITMAP
image_create_bitmap_by_type(Handle self,HPALETTE pal,XBITMAPINFO * bitmapinfo,int bm_type)227 image_create_bitmap_by_type( Handle self, HPALETTE pal, XBITMAPINFO * bitmapinfo, int bm_type)
228 {
229 HBITMAP bm;
230 XBITMAPINFO xbi;
231 BITMAPINFO * bi;
232 HPALETTE old = NULL, xpal = pal;
233 HDC dc;
234 PIcon i = (PIcon) self;
235
236 if ( bm_type == BM_AUTO )
237 bm_type = image_guess_bitmap_type( self );
238
239 if ( bitmapinfo == NULL)
240 bitmapinfo = &xbi;
241 bi = image_fill_bitmap_info( self, bitmapinfo, bm_type);
242 if ( !bi)
243 return NULL;
244
245 dc = GetDC(NULL);
246
247 if ( bi-> bmiHeader. biClrUsed > 0)
248 bi-> bmiHeader. biClrUsed = bi-> bmiHeader. biClrImportant = i-> palSize;
249
250 if ( xpal == NULL)
251 xpal = image_create_palette( self);
252
253 if ( xpal) {
254 old = SelectPalette( dc, xpal, 1);
255 RealizePalette( dc);
256 }
257
258 switch (bm_type) {
259 case BM_BITMAP:
260 if ( i-> type != imBW )
261 warn("panic: image_create_bitmap(BM_BITMAP) called on not a imBW image");
262 bm = CreateBitmap( bi-> bmiHeader. biWidth, bi-> bmiHeader. biHeight, 1, 1, NULL);
263 if (bm)
264 SetDIBits( dc, bm, 0, bi-> bmiHeader. biHeight, i-> data, bi, DIB_RGB_COLORS);
265 break;
266 case BM_PIXMAP:
267 bm = CreateCompatibleBitmap( dc, i->w, i->h);
268 if (bm)
269 SetDIBits( dc, bm, 0, bi-> bmiHeader. biHeight, i-> data, bi, DIB_RGB_COLORS);
270 break;
271 case BM_LAYERED:
272 bm = image_create_argb_bitmap(( Handle) i, NULL );
273 break;
274 default:
275 warn("panic: bad use of image_create_bitmap(%d)", bm_type);
276 return NULL;
277 }
278
279 if ( !bm)
280 apiErr;
281
282 if ( old) {
283 SelectPalette( dc, old, 1);
284 RealizePalette( dc);
285 }
286
287 if ( xpal != pal)
288 DeleteObject( xpal);
289
290 ReleaseDC( NULL, dc);
291
292 return bm;
293 }
294
295 HBITMAP
image_create_bitmap(Handle self)296 image_create_bitmap( Handle self)
297 {
298 return image_create_bitmap_by_type(self, NULL, NULL, BM_AUTO);
299 }
300
301 static XBITMAPINFO a1_info_header = {
302 { sizeof( BITMAPINFOHEADER), 0, 0, 1, 1, BI_RGB, 0, 0, 0, 2, 2},
303 { {0,0,0,0}, {255,255,255,0}}
304 };
305
306 static XBITMAPINFO a8_info_header = {
307 { sizeof( BITMAPINFOHEADER), 0, 0, 1, 8, BI_RGB, 0, 0, 0, 256, 256},
308 { {255,255,255,0}, {0,0,0,0}}
309 };
310
311 static int a_info_headers_initialized = false;
312
313 static XBITMAPINFO *
image_alpha_bitmap_header(int type)314 image_alpha_bitmap_header( int type )
315 {
316 if ( !a_info_headers_initialized ) {
317 a_info_headers_initialized = true;
318 memset( a8_info_header. bmiColors + 1, 0, 255 * sizeof(RGBQUAD));
319 }
320 return (( type == imbpp1 ) ? &a1_info_header : &a8_info_header);
321 }
322
323 /* convert from funky types */
324 static Handle
image_convert_for_gdi(Handle image)325 image_convert_for_gdi( Handle image )
326 {
327 Handle dup;
328 PImage img = (PImage) image;
329
330 if ( !( img-> type & ( imSignedInt | imRealNumber | imComplexNumber | imTrigComplexNumber)))
331 return NULL_HANDLE;
332
333 dup = CImage(image)->dup(image);
334 img = (PImage) dup;
335 img->self->resample(
336 dup,
337 img-> self->stats( dup, false, isRangeLo, 0),
338 img-> self->stats( dup, false, isRangeHi, 0),
339 0, 255
340 );
341 img->self->set_type( dup, imByte );
342 return dup;
343 }
344
345 /* create a copy with given type, unless it is of this type alredy */
346 static Handle
image_convert_to_type(Handle image,int type,Bool inplace)347 image_convert_to_type( Handle image, int type, Bool inplace )
348 {
349 Handle dup;
350
351 if (((PImage)image)->type == type)
352 return NULL_HANDLE;
353
354 dup = inplace ? image : CImage(image)->dup(image);
355 CImage(dup)->set_type(dup, type);
356
357 return dup;
358 }
359
360 #define image_convert_for_bitmap(image,inplace) image_convert_to_type(image,imBW,inplace)
361 #define image_convert_for_rgb(image,inplace) image_convert_to_type(image,imRGB,inplace)
362
363 static Handle
image_convert_rgb_for_screen(Handle image,Bool inplace)364 image_convert_rgb_for_screen( Handle image, Bool inplace )
365 {
366 int bpp;
367 PImage img = (PImage) image;
368
369 if ( img-> type != imRGB)
370 return NULL_HANDLE;
371
372 /* use Prima downsampling methods from RGB to 8,4,1 */
373 bpp = guts. displayBMInfo. bmiHeader. biBitCount *
374 guts. displayBMInfo. bmiHeader. biPlanes;
375 if ( bpp == 0 || bpp > 8)
376 return NULL_HANDLE;
377 if ( bpp < 4) bpp = 1;
378 else if ( bpp < 8) bpp = 4;
379 return image_convert_to_type( image, bpp, inplace );
380 }
381
382 static Handle
image_convert_rgb_for_paletted(Handle image,Handle screen,Bool inplace)383 image_convert_rgb_for_paletted( Handle image, Handle screen, Bool inplace )
384 {
385 int bpp;
386 PImage img = (PImage) image;
387
388 if ( img-> type != imRGB)
389 return NULL_HANDLE;
390
391 if ( dsys( screen) bpp == 0) {
392 if ( !dsys(screen) ps)
393 return image_convert_for_bitmap( image, inplace );
394 dsys( screen) bpp = GetDeviceCaps( dsys(screen) ps, BITSPIXEL);
395 }
396
397 if ( dsys( screen) bpp > 8)
398 return NULL_HANDLE;
399
400 bpp = dsys( screen) bpp;
401 if ( bpp < 4) bpp = 1;
402 else if ( bpp < 8) bpp = 4;
403 return image_convert_to_type( image, bpp, inplace );
404 }
405
406 static void
image_fill_bitmap_cache(Handle self,int bm_type,Handle optimize_for_surface)407 image_fill_bitmap_cache( Handle self, int bm_type, Handle optimize_for_surface)
408 {
409 Handle copy;
410
411 if ( bm_type == BM_AUTO )
412 bm_type = image_guess_bitmap_type( self );
413
414 if ( bm_type == sys s. image. cache. cacheType )
415 return;
416
417 /* free old stuff */
418 image_destroy_cache( self );
419 sys s. image. cache. cacheType = BM_NONE;
420
421 /* create new image, if any */
422 copy = image_convert_for_gdi( self );
423 if ( copy == NULL_HANDLE )
424 copy = self;
425
426 switch (bm_type) {
427 case BM_BITMAP:
428 copy = image_convert_for_bitmap( copy, copy != self);
429 break;
430 case BM_PIXMAP:
431 if (((PImage)copy)-> type == imRGB) {
432 if (!optimize_for_surface)
433 copy = image_convert_rgb_for_screen( copy, copy != self );
434 else if ( dsys(optimize_for_surface) options. aptPrinter ) {
435 /* do nothing, let printer driver do the downsampling */
436 } else if ( ! dsys(optimize_for_surface)options.aptCompatiblePS && dsys(optimize_for_surface)ps)
437 copy = image_convert_rgb_for_paletted( copy, optimize_for_surface, copy != self );
438 else
439 copy = image_convert_rgb_for_screen( copy, copy != self );
440 }
441 break;
442 case BM_LAYERED:
443 copy = image_convert_for_rgb( copy, copy != self);
444 break;
445 default:
446 warn("panic: bad use of image_fill_bitmap_cache(%d)", bm_type);
447 if ( copy != self )
448 Object_destroy(copy);
449 return;
450 }
451 if ( copy == NULL_HANDLE )
452 copy = self;
453
454 /* try to create HBITMAP */
455 switch (bm_type) {
456 case BM_LAYERED:
457 sys bm = image_create_argb_bitmap( copy, &sys s. image. argbBits );
458 if ( !sys bm) {
459 warn("panic: couldn't create argb bitmap");
460 if ( copy != self )
461 Object_destroy(copy);
462 return;
463 }
464 break;
465 default:
466 sys pal = image_create_palette( copy);
467 sys bm = image_create_bitmap_by_type( copy, sys pal, &sys s. image. cache. rawHeader, bm_type );
468 if ( sys bm ) {
469 hash_store( imageMan, &self, sizeof(self), (void*)self);
470 } else {
471 PImage i = (PImage) copy;
472 sys s. image. cache. rawBits = i->data;
473 if ( copy != self ) {
474 i-> data = malloc(1); /* dirty, dirty hack */
475 sys s. image. cache. freeBits = true;
476 }
477 }
478 }
479 if ( copy != self )
480 Object_destroy(copy);
481
482 sys s. image. cache. cacheType = bm_type;
483 }
484
485 void
image_argb_query_bits(Handle self)486 image_argb_query_bits( Handle self)
487 {
488 PIcon i = (PIcon) self;
489 uint32_t * argb_bits;
490 Byte * rgb_bits, *a_bits;
491 int y;
492
493 if ( i-> type != imRGB || i-> maskType != imbpp8)
494 i-> self-> create_empty_icon( self, i-> w, i-> h, imRGB, imbpp8);
495
496 for (
497 y = 0,
498 rgb_bits = i->data,
499 a_bits = i->mask,
500 argb_bits = sys s. image. argbBits;
501 y < i->h;
502 y++,
503 rgb_bits += i-> lineSize,
504 a_bits += i-> maskLine,
505 argb_bits += i-> w
506 ) {
507 register Byte *rgb_ptr = rgb_bits, *a_ptr = a_bits, *argb_ptr = (Byte*) argb_bits;
508 register int x = i->w;
509 for ( ; x > 0; x--) {
510 *rgb_ptr++ = *argb_ptr++;
511 *rgb_ptr++ = *argb_ptr++;
512 *rgb_ptr++ = *argb_ptr++;
513 *a_ptr++ = *argb_ptr++;
514 }
515 }
516 }
517
518 void
image_destroy_cache(Handle self)519 image_destroy_cache( Handle self)
520 {
521 if ( sys bm) {
522 if ( !DeleteObject( sys bm)) apiErr;
523 hash_delete( imageMan, &self, sizeof( self), false);
524 sys bm = NULL;
525 sys s. image. cache. bitmap = NULL;
526 }
527 if ( sys pal) {
528 if ( !DeleteObject( sys pal)) apiErr;
529 sys pal = NULL;
530 }
531 if ( sys s. image. imgCachedRegion) {
532 if ( !DeleteObject( sys s. image. imgCachedRegion)) apiErr;
533 sys s. image. imgCachedRegion = NULL;
534 }
535 if ( sys s. image. cache. freeBits)
536 free( sys s. image. cache. rawBits);
537 sys s. image. cache. rawBits = NULL;
538 sys s. image. cache. freeBits = false;
539 sys s. image. argbBits = NULL;
540 sys s. image. cache. cacheType = BM_NONE;
541 }
542
543 void
image_query_bits(Handle self,Bool forceNewImage)544 image_query_bits( Handle self, Bool forceNewImage)
545 {
546 PImage i = ( PImage) self;
547 XBITMAPINFO xbi;
548 BITMAPINFO * bi;
549 int newBits;
550 HDC ops = NULL;
551 BITMAP bitmap;
552
553 if ( forceNewImage) {
554 ops = sys ps;
555 if ( !ops) {
556 if ( !( sys ps = dc_alloc())) return;
557 }
558 }
559
560 if ( !GetObject( sys bm, sizeof( BITMAP), ( LPSTR) &bitmap)) {
561 apiErr;
562 return;
563 // if GetObject fails to get even BITMAP, there will be no good in farther run for sure.
564 }
565
566 if (( bitmap. bmPlanes == 1) && (
567 ( bitmap. bmBitsPixel == 1) ||
568 ( bitmap. bmBitsPixel == 4) ||
569 ( bitmap. bmBitsPixel == 8) ||
570 ( bitmap. bmBitsPixel == 24)
571 ))
572 newBits = bitmap. bmBitsPixel;
573 else {
574 newBits = ( bitmap. bmBitsPixel <= 4) ? 4 :
575 (( bitmap. bmBitsPixel <= 8) ? 8 : 24);
576 }
577
578
579 if ( forceNewImage) {
580 i-> self-> create_empty( self, bitmap. bmWidth, bitmap. bmHeight, newBits);
581 } else {
582 if (( newBits != ( i-> type & imBPP)) || (( i-> type & ~imBPP) != 0))
583 i-> self-> create_empty( self, i-> w, i-> h, newBits);
584 }
585
586 bi = image_fill_bitmap_info( self, &xbi, BM_PIXMAP);
587
588 if ( !GetDIBits( sys ps, sys bm, 0, i-> h, i-> data, bi, DIB_RGB_COLORS)) apiErr;
589 if (( i-> type & imBPP) < 24) {
590 int j, nColors = 1 << ( i-> type & imBPP);
591 for ( j = 0; j < nColors; j++) {
592 i-> palette[ j]. r = xbi. bmiColors[ j]. rgbRed;
593 i-> palette[ j]. g = xbi. bmiColors[ j]. rgbGreen;
594 i-> palette[ j]. b = xbi. bmiColors[ j]. rgbBlue;
595 }
596 }
597
598 if ( forceNewImage) {
599 if ( !ops) {
600 dc_free();
601 }
602 sys ps = ops;
603 }
604 }
605
606 static Handle ctx_rop2R4[] = {
607 ropCopyPut , SRCCOPY ,
608 ropXorPut , SRCINVERT ,
609 ropAndPut , SRCAND ,
610 ropOrPut , SRCPAINT ,
611 ropNotPut , NOTSRCCOPY ,
612 ropNotDestAnd , SRCERASE ,
613 ropNotDestOr , 0x00DD0228 ,
614 ropNotSrcAnd , 0x00220326 ,
615 ropNotSrcOr , MERGEPAINT ,
616 ropNotXor , 0x00990066 ,
617 ropNotAnd , 0x007700E6 ,
618 ropNotOr , NOTSRCERASE ,
619 ropNoOper , 0x00AA0029 ,
620 ropBlackness , BLACKNESS ,
621 ropWhiteness , WHITENESS ,
622 ropInvert , DSTINVERT ,
623 endCtx
624 };
625
626 static Handle
image_from_dc(Handle image)627 image_from_dc( Handle image )
628 {
629 Handle img = ( Handle) create_object("Prima::Image", "");
630 HDC adc = dsys( image) ps;
631 HBITMAP abitmap = dsys( image) bm;
632 dsys( img) ps = dsys( image) ps;
633 dsys( img) bm = dsys( image) bm;
634 image_query_bits( img, true);
635 dsys( img) ps = adc;
636 dsys( img) bm = abitmap;
637 return img;
638 }
639
640 static int
rop_reduce(COLORREF fore,COLORREF back,int rop)641 rop_reduce(COLORREF fore, COLORREF back, int rop)
642 {
643 /*
644 Special case with current foreground and background colors, see also
645 L<pod/Prima/Drawable.pod | Monochrome bitmaps>.
646
647 Raster ops can be identified by a fingerprint. For example, Or's is 14
648 and Noop's is 10:
649
650 0 | 0 = 0 0 | 0 = 0
651 0 | 1 = 1 0 | 1 = 1
652 1 | 0 = 1 1 | 0 = 0
653 1 | 1 = 1 1 | 1 = 1
654 --- ---
655 1110 = 14 1010 = 10
656
657 when this special case uses not actual 0s and 1s, but bit values of
658 foreground and background color instead, the resulting operation can
659 still be expressed in rops, but these needs to be adjusted. Let's
660 consider a case where both colors are 0, and rop = OrPut:
661
662 0 | 0 = 0
663 0 | 1 = 1
664 0 | 0 = 0
665 0 | 1 = 1
666 ---
667 1010 = 10
668
669 this means that in these conditions, Or (as well as Xor and AndInverted) becomes Noop.
670
671 */
672
673 fore &= 0xffffff;
674 back &= 0xffffff;
675 if ( fore == 0 && back == 0 ) {
676 switch( rop) {
677 case ropAndPut:
678 case ropNotDestAnd:
679 case ropBlackness:
680 case ropCopyPut: rop = ropBlackness; break;
681 case ropNotXor:
682 case ropInvert:
683 case ropNotOr:
684 case ropNotDestOr: rop = ropInvert; break;
685 case ropNotSrcAnd:
686 case ropNoOper:
687 case ropOrPut:
688 case ropXorPut: rop = ropNoOper; break;
689 case ropNotAnd:
690 case ropNotPut:
691 case ropNotSrcOr:
692 case ropWhiteness: rop = ropWhiteness; break;
693 }
694 } else if ( fore != 0 && back == 0 ) {
695 switch( rop) {
696 case ropAndPut: rop = ropNotSrcAnd; break;
697 case ropNotSrcAnd: rop = ropAndPut; break;
698 case ropNotDestAnd: rop = ropNotOr; break;
699 case ropBlackness: rop = ropBlackness; break;
700 case ropCopyPut: rop = ropNotPut; break;
701 case ropNotPut: rop = ropCopyPut; break;
702 case ropNotXor: rop = ropXorPut; break;
703 case ropInvert: rop = ropInvert; break;
704 case ropNotAnd: rop = ropNotDestOr; break;
705 case ropNoOper: rop = ropNoOper; break;
706 case ropNotOr: rop = ropNotDestAnd; break;
707 case ropOrPut: rop = ropNotSrcOr; break;
708 case ropNotSrcOr: rop = ropOrPut; break;
709 case ropNotDestOr: rop = ropNotAnd; break;
710 case ropWhiteness: rop = ropWhiteness; break;
711 case ropXorPut: rop = ropNotXor; break;
712 }
713 } else if ( fore != 0 && back != 0 ) {
714 switch( rop) {
715 case ropAndPut:
716 case ropNotSrcOr:
717 case ropNotXor:
718 case ropNoOper: rop = ropNoOper; break;
719 case ropNotSrcAnd:
720 case ropBlackness:
721 case ropNotPut:
722 case ropNotOr: rop = ropBlackness; break;
723 case ropInvert:
724 case ropNotAnd:
725 case ropNotDestAnd:
726 case ropXorPut: rop = ropInvert; break;
727 case ropOrPut:
728 case ropNotDestOr:
729 case ropWhiteness:
730 case ropCopyPut: rop = ropWhiteness; break;
731 }
732 }
733 return rop;
734 }
735
736 typedef struct {
737 HDC src;
738 int src_x;
739 int src_y;
740 int src_w;
741 int src_h;
742 int dst_x;
743 int dst_y;
744 int dst_w;
745 int dst_h;
746 int rop;
747 } PutImageRequest;
748
749 typedef Bool PutImageFunc( Handle self, Handle image, PutImageRequest * req);
750
751 #define SRC_BITMAP 0
752 #define SRC_PIXMAP 1
753 #define SRC_LAYERED 2
754 #define SRC_IMAGE 3
755 #define SRC_A8 4
756 #define SRC_ARGB 5
757 #define SRC_MAX 5
758 #define SRC_NUM SRC_MAX+1
759
760 static Bool
img_put_stretch_blt(HDC dst,HDC src,PutImageRequest * req)761 img_put_stretch_blt( HDC dst, HDC src, PutImageRequest * req)
762 {
763 Bool ok = true;
764 int rop = ctx_remap_def( req->rop, ctx_rop2R4, true, SRCCOPY);
765 if ( !StretchBlt(
766 dst, req-> dst_x, req-> dst_y, req-> dst_w, req-> dst_h,
767 src, req-> src_x, req-> src_y, req-> src_w, req-> src_h,
768 rop)) {
769 apiErr;
770 ok = false;
771 }
772 return ok;
773 }
774
775 static Bool
img_put_stretch_bits(HDC dst,Handle self,PutImageRequest * req)776 img_put_stretch_bits( HDC dst, Handle self, PutImageRequest * req)
777 {
778 int rop;
779
780 if ( !sys s. image. cache. rawBits )
781 return false;
782
783 rop = ctx_remap_def( req->rop, ctx_rop2R4, true, SRCCOPY);
784 if ( StretchDIBits( dst,
785 req-> dst_x, req-> dst_y, req-> dst_w, req-> dst_h,
786 req-> src_x, req-> src_y, req-> src_w, req-> src_h,
787 sys s. image. cache. rawBits, (BITMAPINFO*) & sys s. image. cache. rawHeader,
788 DIB_RGB_COLORS, rop) == GDI_ERROR) {
789 apiErr;
790 return false;
791 }
792
793 return true;
794 }
795
796 static Bool
img_put_and_mask(HDC dst,Handle image,PutImageRequest * req)797 img_put_and_mask( HDC dst, Handle image, PutImageRequest * req)
798 {
799 XBITMAPINFO * bi = image_alpha_bitmap_header(PIcon(image)->maskType);
800
801 bi-> bmiHeader. biWidth = ((PImage)image)-> w;
802 bi-> bmiHeader. biHeight = ((PImage)image)-> h;
803
804 if ( StretchDIBits( dst,
805 req-> dst_x, req-> dst_y, req-> dst_w, req-> dst_h,
806 req-> src_x, req-> src_y, req-> src_w, req-> src_h,
807 PIcon(image)->mask, (BITMAPINFO*) bi, DIB_RGB_COLORS, SRCAND
808 ) == GDI_ERROR) {
809 apiErr;
810 return false;
811 }
812 return true;
813 }
814
815 static Bool
img_put_image_on_bitmap_or_pixmap(Handle self,Handle image,PutImageRequest * req,int bm_type)816 img_put_image_on_bitmap_or_pixmap( Handle self, Handle image, PutImageRequest * req, int bm_type)
817 {
818 Bool ok;
819 HDC src;
820 HPALETTE pal_src, pal_src_save, pal_dst_save;
821 HBITMAP bm_src_save;
822 COLORREF oFore = 0, oBack = 0;
823 PImage i = (PImage) image;
824
825 image_fill_bitmap_cache( image, bm_type, self );
826 if ( dsys( image) bm == NULL ) /* we're low on memory, reverting to StretchDIBits */
827 return img_put_stretch_bits( sys ps, image, req);
828
829 /* create and prepare DC */
830 src = CreateCompatibleDC( sys ps);
831
832 if (( pal_src = dsys( image) pal) != NULL)
833 pal_src_save = SelectPalette( src, pal_src, 0);
834 else
835 pal_src_save = NULL;
836
837 bm_src_save = SelectObject( src, dsys( image) bm);
838 if ( pal_src) {
839 pal_dst_save = SelectPalette( sys ps, pal_src, 1);
840 RealizePalette( sys ps);
841 } else
842 pal_dst_save = NULL;
843
844 if ((bm_type == BM_PIXMAP) && (( i->type & imBPP) == 1)) {
845 oFore = GetTextColor( sys ps);
846 oBack = GetBkColor( sys ps);
847 SetTextColor( sys ps, 0x00000000);
848 SetBkColor ( sys ps, 0x00FFFFFF);
849 }
850
851 /* draw */
852 ok = img_put_stretch_blt( sys ps, src, req );
853
854 /* clean up */
855 if ((bm_type == BM_PIXMAP) && (( i->type & imBPP) == 1)) {
856 SetTextColor( sys ps, oFore);
857 SetBkColor( sys ps, oBack);
858 }
859
860 if ( pal_src) {
861 if ( pal_src_save) SelectPalette( src, pal_src_save, 1);
862 }
863 if ( pal_dst_save) {
864 if ( is_apt(aptCompatiblePS))
865 SelectPalette( sys ps, pal_dst_save, 1);
866 else {
867 DeleteObject( pal_dst_save );
868 dsys( image) pal = image_create_palette( image);
869 }
870 }
871 if ( bm_src_save) SelectObject( src, bm_src_save);
872 DeleteDC( src);
873
874 return ok;
875 }
876
877 static Bool
img_put_alpha_blend(HDC dst,HDC src,PutImageRequest * req)878 img_put_alpha_blend( HDC dst, HDC src, PutImageRequest * req)
879 {
880 Bool ok;
881 BLENDFUNCTION bf;
882 bf.BlendOp = AC_SRC_OVER;
883 bf.BlendFlags = 0;
884 bf.SourceConstantAlpha = 0xff;
885 bf.AlphaFormat = AC_SRC_ALPHA;
886 ok = AlphaBlend(
887 dst, req-> dst_x, req-> dst_y, req-> dst_w, req-> dst_h,
888 src, req-> src_x, req-> src_y, req-> src_w, req-> src_h,
889 bf);
890
891 if (!ok) apiErr;
892 return ok;
893 }
894
895 /* on bitmap */
896 static Bool
img_put_bitmap_on_bitmap(Handle self,Handle image,PutImageRequest * req)897 img_put_bitmap_on_bitmap( Handle self, Handle image, PutImageRequest * req)
898 {
899 STYLUS_USE_TEXT( sys ps);
900 STYLUS_USE_BRUSH( sys ps);
901 if ( dsys( image) options. aptDeviceBitmap )
902 req-> rop = rop_reduce(GetTextColor( sys ps), GetBkColor( sys ps), req-> rop);
903 return img_put_stretch_blt( sys ps, dsys(image)ps, req);
904 }
905
906 static Bool
img_put_pixmap_on_bitmap(Handle self,Handle image,PutImageRequest * req)907 img_put_pixmap_on_bitmap( Handle self, Handle image, PutImageRequest * req)
908 {
909 return img_put_stretch_blt( sys ps, dsys(image)ps, req);
910 }
911
912 static Bool
img_put_image_on_bitmap(Handle self,Handle image,PutImageRequest * req)913 img_put_image_on_bitmap( Handle self, Handle image, PutImageRequest * req)
914 {
915 return img_put_image_on_bitmap_or_pixmap( self, image, req, BM_BITMAP);
916 }
917
918 static Bool
img_put_argb_on_bitmap(Handle self,Handle image,PutImageRequest * req)919 img_put_argb_on_bitmap( Handle self, Handle image, PutImageRequest * req)
920 {
921 if ( !img_put_and_mask( sys ps, image, req))
922 return false;
923 req-> rop = (req->rop == ropSrcCopy) ? ropCopyPut : ropOrPut;
924 return img_put_image_on_bitmap( self, image, req );
925 }
926
927 static Bool
img_put_layered_on_bitmap(Handle self,Handle image,PutImageRequest * req)928 img_put_layered_on_bitmap( Handle self, Handle image, PutImageRequest * req)
929 {
930 Bool ok;
931 Handle icon;
932 PIcon i;
933 uint32_t * argb_bits;
934 Byte * rgb_bits, *a_bits;
935 int y;
936
937 icon = (Handle) create_object("Prima::Icon", "");
938 i = (PIcon) icon;
939
940 CIcon(icon)-> create_empty_icon( icon, req->src_w, req->src_h, imRGB, imbpp8);
941 for (
942 y = 0,
943 rgb_bits = i->data,
944 a_bits = i->mask,
945 argb_bits = dsys(image) s. image. argbBits + req->src_y * i-> w + req-> src_x;
946 y < req-> src_h;
947 y++,
948 rgb_bits += i-> lineSize,
949 a_bits += i-> maskLine,
950 argb_bits += i-> w
951 ) {
952 register Byte *rgb_ptr = rgb_bits, *a_ptr = a_bits, *argb_ptr = (Byte*) argb_bits;
953 register int x = req-> src_w;
954 for ( ; x > 0; x--) {
955 *rgb_ptr++ = *argb_ptr++;
956 *rgb_ptr++ = *argb_ptr++;
957 *rgb_ptr++ = *argb_ptr++;
958 *a_ptr++ = *argb_ptr++;
959 }
960 }
961 ok = img_put_argb_on_bitmap( self, icon, req);
962 Object_destroy( icon );
963 return ok;
964 }
965
966 /* on pixmap */
967 static Bool
img_put_monodc_on_pixmap(HDC dst,HDC src,PutImageRequest * req)968 img_put_monodc_on_pixmap( HDC dst, HDC src, PutImageRequest * req)
969 {
970 Bool ok;
971 COLORREF oFore = GetTextColor( dst);
972 COLORREF oBack = GetBkColor( dst);
973 SetTextColor( dst, 0x00000000);
974 SetBkColor ( dst, 0x00FFFFFF);
975 ok = img_put_stretch_blt( dst, src, req);
976 SetTextColor( dst, oFore);
977 SetBkColor ( dst, oBack);
978 return ok;
979 }
980
981 static Bool
img_put_bitmap_on_pixmap(Handle self,Handle image,PutImageRequest * req)982 img_put_bitmap_on_pixmap( Handle self, Handle image, PutImageRequest * req)
983 {
984 if ( dsys( image) options. aptDeviceBitmap ) {
985 STYLUS_USE_TEXT( sys ps);
986 STYLUS_USE_BRUSH( sys ps);
987 return img_put_stretch_blt( sys ps, dsys(image)ps, req);
988 } else
989 return img_put_monodc_on_pixmap( sys ps, dsys(image)ps, req);
990 }
991
992 static Bool
img_put_image_on_pixmap(Handle self,Handle image,PutImageRequest * req)993 img_put_image_on_pixmap( Handle self, Handle image, PutImageRequest * req)
994 {
995 return img_put_image_on_bitmap_or_pixmap( self, image, req, BM_PIXMAP);
996 }
997
998 static Bool
img_put_pixmap_on_pixmap(Handle self,Handle image,PutImageRequest * req)999 img_put_pixmap_on_pixmap( Handle self, Handle image, PutImageRequest * req)
1000 {
1001 if ( dsys( image ) options. aptImage && (( PImage(image)-> type & imBPP ) == 1))
1002 return img_put_monodc_on_pixmap( sys ps, dsys(image)ps, req);
1003 else if ( !dsys(image) options. aptCompatiblePS) {
1004 Bool ok;
1005 Handle img = image_from_dc(image);
1006 ok = img_put_image_on_pixmap(self, img, req);
1007 Object_destroy( img);
1008 return ok;
1009 } else
1010 return img_put_stretch_blt( sys ps, dsys(image)ps, req);
1011 }
1012
1013 static Bool
img_put_argb_on_pixmap(Handle self,Handle image,PutImageRequest * req)1014 img_put_argb_on_pixmap( Handle self, Handle image, PutImageRequest * req)
1015 {
1016 Bool ok;
1017 HDC src;
1018 HBITMAP old;
1019
1020 if ( req-> rop == ropSrcCopy ) {
1021 req-> rop = ropCopyPut;
1022 return img_put_image_on_pixmap( self, image, req);
1023 }
1024
1025 image_fill_bitmap_cache( image, BM_LAYERED, self );
1026 if ( dsys(image) bm == NULL)
1027 return false;
1028
1029 src = CreateCompatibleDC(sys ps);
1030 old = SelectObject(src, dsys (image) bm);
1031 ok = img_put_alpha_blend( sys ps, src, req);
1032 SelectObject(src, old);
1033 DeleteDC(src);
1034
1035 return ok;
1036 }
1037
1038 static Bool
img_put_layered_on_pixmap(Handle self,Handle image,PutImageRequest * req)1039 img_put_layered_on_pixmap( Handle self, Handle image, PutImageRequest * req)
1040 {
1041 if ( req-> rop == ropSrcCopy ) {
1042 req-> rop = ropCopyPut;
1043 return img_put_pixmap_on_pixmap( self, image, req);
1044 } else
1045 return img_put_alpha_blend( sys ps, dsys(image)ps, req);
1046 }
1047
1048 /* layered */
1049 static void
img_draw_black_rect(Handle self,PutImageRequest * req)1050 img_draw_black_rect( Handle self, PutImageRequest * req)
1051 {
1052 HGDIOBJ oldp = SelectObject( sys ps, hPenHollow);
1053 HGDIOBJ oldh = SelectObject( sys ps, CreateSolidBrush( RGB(0,0,0 )));
1054 if ( !SetROP2( sys ps, R2_COPYPEN)) apiErr;
1055 if ( !Rectangle( sys ps, req-> dst_x, req-> dst_y, req-> dst_x + req-> dst_w + 1, req-> dst_y + req-> dst_h + 1)) apiErr;
1056 if ( !SetROP2( sys ps, sys currentROP)) apiErr;
1057 SelectObject( sys ps, oldp);
1058 DeleteObject( SelectObject( sys ps, oldh));
1059 }
1060
1061 static Bool
img_put_argb_on_layered(Handle self,Handle image,PutImageRequest * req)1062 img_put_argb_on_layered( Handle self, Handle image, PutImageRequest * req)
1063 {
1064 Bool ok;
1065 HDC src;
1066 HBITMAP old;
1067
1068 image_fill_bitmap_cache( image, BM_LAYERED, self );
1069 if ( dsys(image) bm == NULL)
1070 return false;
1071
1072 src = CreateCompatibleDC(sys ps);
1073 old = SelectObject(src, dsys (image) bm);
1074 if ( req-> rop == ropSrcCopy ) {
1075 req-> rop = ropCopyPut;
1076 img_draw_black_rect( self, req );
1077 ok = img_put_stretch_blt( sys ps, src, req);
1078 } else
1079 ok = img_put_alpha_blend( sys ps, src, req);
1080 SelectObject(src, old);
1081 DeleteDC(src);
1082
1083 return ok;
1084 }
1085
1086 static Bool
img_put_a8_on_layered(Handle self,Handle image,PutImageRequest * req)1087 img_put_a8_on_layered( Handle self, Handle image, PutImageRequest * req)
1088 {
1089 Bool ok;
1090 HDC dc, buf_dc;
1091 HBITMAP buf_bm, old_bm;
1092 PImage i;
1093 unsigned int dst_lw, src_lw, y;
1094 Byte *src, *dst;
1095
1096 i = (PImage) image;
1097 if ( i-> type != imByte || i-> w != req-> dst_w || i-> h != req-> dst_h ) {
1098 Handle dup = CImage( image )->dup(image);
1099 if ( i-> type != imByte )
1100 CImage( dup )->set_type(dup, imByte);
1101 if (i-> w != req-> dst_w || i-> h != req-> dst_h )
1102 CImage( dup )->stretch(dup, req->dst_w, req-> dst_h);
1103 ok = img_put_a8_on_layered( self, dup, req);
1104 Object_destroy(dup);
1105 return ok;
1106 }
1107
1108 dc = GetDC(NULL);
1109 buf_dc = CreateCompatibleDC(dc);
1110 if ( !(buf_bm = image_create_argb_dib_section(dc, req-> dst_w, req-> dst_h, (uint32_t**) &dst))) {
1111 DeleteDC(buf_dc);
1112 ReleaseDC(NULL, dc);
1113 return false;
1114 }
1115
1116 old_bm = SelectObject(buf_dc, buf_bm);
1117
1118 BitBlt( buf_dc, 0, 0, req-> dst_w, req-> dst_h, sys ps, req-> dst_x, req-> dst_y, SRCCOPY);
1119
1120 src = i-> data;
1121 dst_lw = req-> dst_w * 4;
1122 src_lw = i-> lineSize;
1123 for ( y = 0; y < i-> h; y++, src += src_lw, dst += dst_lw ) {
1124 register Byte *ss = src, *dd = dst + 3;
1125 register unsigned int w = i-> w;
1126 while (w--) {
1127 *dd = *ss++;
1128 dd += 4;
1129 }
1130 }
1131
1132 BitBlt( sys ps, req-> dst_x, req-> dst_y, req-> dst_w, req-> dst_h, buf_dc, 0, 0, SRCCOPY);
1133
1134 SelectObject(buf_dc, old_bm);
1135 DeleteDC(buf_dc);
1136 DeleteObject(buf_bm);
1137 ReleaseDC(NULL, dc);
1138 return true;
1139 }
1140
1141 static Bool
img_put_layered_on_layered(Handle self,Handle image,PutImageRequest * req)1142 img_put_layered_on_layered( Handle self, Handle image, PutImageRequest * req)
1143 {
1144 if ( req-> rop == ropSrcCopy ) {
1145 req-> rop = ropCopyPut;
1146 img_draw_black_rect( self, req );
1147 return img_put_stretch_blt( sys ps, dsys(image)ps, req);
1148 } else
1149 return img_put_alpha_blend( sys ps, dsys(image)ps, req);
1150 }
1151
1152 PutImageFunc (*img_put_on_bitmap[SRC_NUM]) = {
1153 img_put_bitmap_on_bitmap,
1154 img_put_pixmap_on_bitmap,
1155 img_put_layered_on_bitmap,
1156 img_put_image_on_bitmap,
1157 img_put_image_on_bitmap,
1158 img_put_argb_on_bitmap,
1159 };
1160
1161 PutImageFunc (*img_put_on_pixmap[SRC_NUM]) = {
1162 img_put_bitmap_on_pixmap,
1163 img_put_pixmap_on_pixmap,
1164 img_put_layered_on_pixmap,
1165 img_put_image_on_pixmap,
1166 img_put_image_on_pixmap,
1167 img_put_argb_on_pixmap,
1168 };
1169
1170 PutImageFunc (*img_put_on_layered[SRC_NUM]) = {
1171 img_put_bitmap_on_pixmap,
1172 img_put_pixmap_on_pixmap,
1173 img_put_layered_on_layered,
1174 img_put_image_on_pixmap,
1175 img_put_a8_on_layered,
1176 img_put_argb_on_layered,
1177 };
1178
1179 Bool
apc_gp_stretch_image(Handle self,Handle image,int dst_x,int dst_y,int src_x,int src_y,int dst_w,int dst_h,int src_w,int src_h,int rop)1180 apc_gp_stretch_image( Handle self, Handle image,
1181 int dst_x, int dst_y, int src_x, int src_y,
1182 int dst_w, int dst_h, int src_w, int src_h, int rop)
1183 {
1184 PIcon img = (PIcon) image;
1185 PutImageRequest req;
1186 PutImageFunc ** dst = NULL;
1187 int src = -1;
1188 Bool and_mask = false;
1189
1190 objCheck false;
1191 dobjCheck(image) false;
1192
1193 if ( src_h < 0) {
1194 src_h = -src_h;
1195 dst_h = -dst_h;
1196 }
1197 if ( src_w < 0) {
1198 src_w = -src_w;
1199 dst_w = -dst_w;
1200 }
1201 if ( abs(src_x) >= img-> w) return false;
1202 if ( abs(src_y) >= img-> h) return false;
1203 if ( src_w == 0 || src_h == 0) return false;
1204 if ( src_x < 0) {
1205 dst_x -= src_x * dst_w / src_w;
1206 dst_w += src_x * dst_w / src_w;
1207 src_w += src_x;
1208 src_x = 0;
1209 }
1210 if ( src_y < 0) {
1211 dst_y -= src_y * dst_h / src_h;
1212 dst_h += src_y * dst_h / src_h;
1213 src_h += src_y;
1214 src_y = 0;
1215 }
1216 if ( src_x + src_w > img-> w) {
1217 dst_w = (img-> w - src_x) * dst_w / src_w;
1218 src_w = img-> w - src_x;
1219 }
1220 if ( src_y + src_h > img-> h) {
1221 dst_h = (img-> h - src_y) * dst_h / src_h;
1222 src_h = img-> h - src_y;
1223 }
1224 if ( src_w <= 0 || src_h <= 0) return false;
1225
1226 memset( &req, 0, sizeof(req));
1227 req. src_x = src_x;
1228 req. src_y = img->h - src_y - src_h;
1229 req. src_w = src_w;
1230 req. src_h = src_h;
1231 req. dst_x = sys gp_transform.x + dst_x;
1232 req. dst_y = sys gp_transform.y + sys lastSize. y - dst_y - dst_h;
1233 req. dst_w = dst_w;
1234 req. dst_h = dst_h;
1235 req. rop = rop;
1236
1237 if ( dsys( image) options. aptDeviceBitmap ) {
1238 PDeviceBitmap p = (PDeviceBitmap) image;
1239 switch (p->type) {
1240 case dbtBitmap: src = SRC_BITMAP; break;
1241 case dbtPixmap: src = SRC_PIXMAP; break;
1242 case dbtLayered: src = SRC_LAYERED; break;
1243 }
1244 } else if ( dsys( image) options. aptIcon ) {
1245 Bool src_mono = img-> type == imBW;
1246 if ( img-> maskType == imbpp1 || guts. displayBMInfo. bmiHeader. biBitCount <= 8) {
1247 if ( img-> options. optInDraw )
1248 src = src_mono ? SRC_BITMAP : SRC_PIXMAP;
1249 else
1250 src = SRC_IMAGE;
1251 and_mask = true;
1252 } else if ( img-> maskType == imbpp8 ) {
1253 if ( img-> options. optInDraw ) {
1254 src = SRC_LAYERED;
1255 } else
1256 src = SRC_ARGB;
1257 }
1258 } else if ( dsys( image) options. aptImage ) {
1259 Bool src_mono = img-> type == imBW;
1260 if ( img-> options. optInDraw )
1261 src = src_mono ? SRC_BITMAP : SRC_PIXMAP;
1262 else
1263 src = SRC_IMAGE;
1264 }
1265 if ( src < 0 ) {
1266 warn("cannot guess image type");
1267 return false;
1268 }
1269
1270 if (( is_apt(aptDeviceBitmap) && ((PDeviceBitmap)self)->type == dbtBitmap) ||
1271 ( is_apt(aptImage) && ((PImage)self)-> type == imBW ))
1272 dst = img_put_on_bitmap;
1273 else if ( is_apt(aptLayered))
1274 dst = img_put_on_layered;
1275 else if (( is_apt(aptDeviceBitmap) && ((PDeviceBitmap)self)->type == dbtPixmap) ||
1276 (is_apt(aptImage) && ((PImage)self)-> type != imBW ))
1277 dst = img_put_on_pixmap;
1278 else if ( apc_widget_get_layered_request(self) && apc_widget_surface_is_layered(self))
1279 dst = img_put_on_layered;
1280 else
1281 dst = img_put_on_pixmap;
1282
1283 if (
1284 dst == img_put_on_layered &&
1285 src == SRC_IMAGE &&
1286 !dsys( image) options. aptIcon &&
1287 (((PImage)image)->type & imGrayScale) &&
1288 rop == ropAlphaCopy ) {
1289 src = SRC_A8;
1290 rop = ropCopyPut;
1291 }
1292
1293 if ( rop > ropNoOper ) return false;
1294
1295 if ( dst[src] == NULL ) {
1296 warn("not implemented");
1297 return false;
1298 }
1299
1300 if ( and_mask ) {
1301 if ( !img_put_and_mask(sys ps, image, &req))
1302 return false;
1303 req. rop = ropXorPut;
1304 }
1305
1306 return (*dst[src])(self, image, &req);
1307 }
1308
1309
1310 Bool
apc_image_create(Handle self)1311 apc_image_create( Handle self)
1312 {
1313 objCheck false;
1314 apt_set( aptImage);
1315 if ( kind_of( self, CIcon )) apt_set( aptIcon );
1316 image_destroy_cache( self);
1317 sys lastSize. x = var w;
1318 sys lastSize. y = var h;
1319 return true;
1320 }
1321
1322 Bool
apc_image_destroy(Handle self)1323 apc_image_destroy( Handle self)
1324 {
1325 objCheck false;
1326 image_destroy_cache( self);
1327 return true;
1328 }
1329
1330 Bool
apc_image_begin_paint(Handle self)1331 apc_image_begin_paint( Handle self)
1332 {
1333 apcErrClear;
1334 objCheck false;
1335 image_fill_bitmap_cache( self, BM_AUTO, NULL_HANDLE);
1336 if ( sys bm == NULL ) {
1337 image_destroy_cache( self );
1338 return false;
1339 }
1340 if ( !( sys ps = CreateCompatibleDC( 0))) apiErrRet;
1341 sys stockBM = SelectObject( sys ps, sys bm);
1342 hwnd_enter_paint( self);
1343
1344 apt_clear( aptLayered );
1345 if ( is_apt( aptIcon ) && PIcon(self)-> maskType == imbpp8 ) {
1346 sys bpp = 32;
1347 apt_set( aptLayered );
1348 }
1349 else if ( PImage( self)-> type == imBW)
1350 sys bpp = 1;
1351 if ( sys pal) {
1352 SelectPalette( sys ps, sys pal, 0);
1353 RealizePalette( sys ps);
1354 }
1355 return true;
1356 }
1357
1358 Bool
apc_image_begin_paint_info(Handle self)1359 apc_image_begin_paint_info( Handle self)
1360 {
1361 apcErrClear;
1362 objCheck false;
1363 if ( !( sys ps = CreateCompatibleDC( 0))) apiErrRet;
1364 if ( !sys pal) sys pal = image_create_palette( self);
1365 if ( sys pal) SelectPalette( sys ps, sys pal, 0);
1366 hwnd_enter_paint( self);
1367 if ( PImage( self)-> type == imBW)
1368 sys bpp = 1;
1369 else if ( is_apt( aptIcon ) && PIcon(self)-> maskType == imbpp8 ) {
1370 sys bpp = 32;
1371 apt_set( aptLayered );
1372 }
1373 return true;
1374 }
1375
1376 Bool
apc_image_end_paint(Handle self)1377 apc_image_end_paint( Handle self)
1378 {
1379 apcErrClear;
1380 objCheck false;
1381
1382 if ( is_apt( aptLayered))
1383 image_argb_query_bits( self);
1384 else
1385 image_query_bits( self, false);
1386 hwnd_leave_paint( self);
1387 if ( sys stockBM)
1388 SelectObject( sys ps, sys stockBM);
1389 DeleteDC( sys ps);
1390 sys stockBM = NULL;
1391 sys ps = NULL;
1392 return apcError == errOk;
1393 }
1394
1395 Bool
apc_image_end_paint_info(Handle self)1396 apc_image_end_paint_info( Handle self)
1397 {
1398 objCheck false;
1399 apcErrClear;
1400 hwnd_leave_paint( self);
1401 DeleteDC( sys ps);
1402 sys ps = NULL;
1403 return apcError == errOk;
1404 }
1405
1406
1407 Bool
apc_image_update_change(Handle self)1408 apc_image_update_change( Handle self)
1409 {
1410 objCheck false;
1411 image_destroy_cache( self);
1412 sys lastSize. x = var w;
1413 sys lastSize. y = var h;
1414 return true;
1415 }
1416
1417 HBITMAP
image_create_argb_dib_section(HDC dc,int w,int h,uint32_t ** ptr)1418 image_create_argb_dib_section( HDC dc, int w, int h, uint32_t ** ptr)
1419 {
1420 HBITMAP bm;
1421 BITMAPINFO bmi;
1422 uint32_t * dummy;
1423
1424 if ( !ptr ) ptr = &dummy;
1425
1426 ZeroMemory(&bmi, sizeof(BITMAPINFO));
1427 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1428 bmi.bmiHeader.biWidth = w;
1429 bmi.bmiHeader.biHeight = h;
1430 bmi.bmiHeader.biPlanes = 1;
1431 bmi.bmiHeader.biBitCount = 32;
1432 bmi.bmiHeader.biCompression = BI_RGB;
1433 bmi.bmiHeader.biSizeImage = w * h * 4;
1434 if ( !( bm = CreateDIBSection(dc, &bmi, DIB_RGB_COLORS, (LPVOID*)ptr, NULL, 0x0))) {
1435 apiErr;
1436 return NULL;
1437 }
1438 return bm;
1439 }
1440
1441 Bool
apc_dbm_create(Handle self,int type)1442 apc_dbm_create( Handle self, int type)
1443 {
1444 HDC dc;
1445 Bool palc = 0;
1446
1447 objCheck false;
1448 apcErrClear;
1449 apt_set( aptBitmap);
1450 apt_set( aptDeviceBitmap);
1451 apt_set( aptCompatiblePS);
1452
1453 if ( !( sys ps = CreateCompatibleDC( 0))) apiErrRet;
1454 sys lastSize. x = var w;
1455 sys lastSize. y = var h;
1456
1457 if ( type == dbtLayered && guts. displayBMInfo. bmiHeader. biBitCount <= 8)
1458 type = dbtPixmap;
1459
1460 switch ( type ) {
1461 case dbtBitmap:
1462 dc = NULL;
1463 sys bm = CreateBitmap( var w, var h, 1, 1, NULL);
1464 break;
1465 case dbtPixmap:
1466 if (!( dc = dc_alloc())) {
1467 DeleteDC( sys ps);
1468 return false;
1469 }
1470 if (( sys pal = palette_create( self))) {
1471 sys stockPalette = SelectPalette( sys ps, sys pal, 1);
1472 RealizePalette( sys ps);
1473 palc = 1;
1474 }
1475 sys bm = CreateCompatibleBitmap( dc, var w, var h);
1476 if ( guts. displayBMInfo. bmiHeader. biBitCount == 8)
1477 apt_clear( aptCompatiblePS);
1478 break;
1479 case dbtLayered:
1480 apt_set( aptLayered );
1481 if (!( dc = dc_alloc())) {
1482 DeleteDC( sys ps);
1483 return false;
1484 }
1485 sys bm = image_create_argb_dib_section( dc, var w, var h, &sys s. image. argbBits);
1486 break;
1487 default:
1488 DeleteDC( sys ps);
1489 return false;
1490 }
1491
1492 if ( !sys bm) {
1493 apiErr;
1494 if ( dc) dc_free();
1495 if ( palc) {
1496 SelectPalette( sys ps, sys stockPalette, 1);
1497 DeleteObject( sys stockPalette);
1498 sys stockPalette = NULL;
1499 }
1500 DeleteDC( sys ps);
1501 return false;
1502 }
1503 if ( dc) dc_free();
1504
1505 sys stockBM = SelectObject( sys ps, sys bm);
1506
1507 hwnd_enter_paint( self);
1508 switch ( type ) {
1509 case dbtBitmap:
1510 sys bpp = 1;
1511 break;
1512 case dbtLayered:
1513 sys bpp = 32;
1514 break;
1515 }
1516
1517 hash_store( imageMan, &self, sizeof( self), (void*)self);
1518 return true;
1519 }
1520
1521 void
dbm_recreate(Handle self)1522 dbm_recreate( Handle self)
1523 {
1524 HBITMAP bm, stock;
1525 HDC dc, dca;
1526 HPALETTE p = NULL;
1527 Event ev = {cmSysHandle};
1528
1529 if ((( PDeviceBitmap) self)-> type != dbtPixmap ) return;
1530
1531 if ( !( dc = CreateCompatibleDC( 0))) {
1532 apiErr;
1533 return;
1534 }
1535 if (!( dca = dc_alloc())) {
1536 DeleteDC( dc);
1537 return;
1538 }
1539
1540 if ( sys pal) {
1541 p = SelectPalette( dc, sys pal, 1);
1542 RealizePalette( dc);
1543 }
1544
1545 if ( !( bm = CreateCompatibleBitmap( dca, var w, var h))) {
1546 DeleteDC( dc);
1547 dc_free();
1548 apiErr;
1549 return;
1550 }
1551 stock = SelectObject( dc, bm);
1552
1553 BitBlt( dc, 0, 0, var w, var h, sys ps, 0, 0, SRCCOPY);
1554
1555 if ( sys pal) {
1556 SelectPalette( sys ps, sys stockPalette, 1);
1557 sys stockPalette = p;
1558 } else
1559 sys stockPalette = GetCurrentObject( dc, OBJ_PAL);
1560
1561 if ( sys stockBM)
1562 SelectObject( sys ps, sys stockBM);
1563 DeleteObject( sys bm);
1564 DeleteDC( sys ps);
1565
1566 sys ps = dc;
1567 sys bm = bm;
1568 sys stockBM = stock;
1569 dc_free();
1570
1571 ev. gen. source = self;
1572 var self-> message( self, &ev);
1573 }
1574
1575 Bool
apc_dbm_destroy(Handle self)1576 apc_dbm_destroy( Handle self)
1577 {
1578 apcErrClear;
1579 hash_delete( imageMan, &self, sizeof( self), false);
1580 objCheck false;
1581
1582 hwnd_leave_paint( self);
1583
1584 if ( sys pal)
1585 DeleteObject( sys pal);
1586 if ( sys stockBM)
1587 SelectObject( sys ps, sys stockBM);
1588 DeleteObject( sys bm);
1589 DeleteDC( sys ps);
1590 sys pal = NULL;
1591 sys stockBM = NULL;
1592 sys ps = NULL;
1593 sys bm = NULL;
1594 return true;
1595 }
1596
1597 HICON
image_make_icon_handle(Handle img,Point size,Point * hotSpot)1598 image_make_icon_handle( Handle img, Point size, Point * hotSpot)
1599 {
1600 PIcon i = ( PIcon) img;
1601 HICON r;
1602 ICONINFO ii;
1603 int bpp = i-> type & imBPP;
1604 Bool noSZ = i-> w != size. x || i-> h != size. y;
1605 Bool noBPP = bpp != 1 && bpp != 4 && bpp != 8 && bpp != 24;
1606 HDC dc;
1607 Bool notAnIcon = !dsys( img ) options. aptIcon;
1608
1609 ii. fIcon = hotSpot ? false : true;
1610 ii. xHotspot = hotSpot ? hotSpot-> x : 0;
1611 ii. yHotspot = hotSpot ? hotSpot-> y : 0;
1612
1613 if (!notAnIcon && i->maskType == 8 && bpp != 24 ) {
1614 bpp = 24;
1615 noBPP = true;
1616 }
1617
1618 if ( noSZ || noBPP) {
1619 i = ( PIcon)( i-> self-> dup( img));
1620
1621 if ( noSZ)
1622 i-> self-> set_size(( Handle) i, size);
1623 if ( noBPP)
1624 i-> self-> set_type(( Handle) i,
1625 ( bpp < 4) ? 1 :
1626 (( bpp < 8) ? 4 :
1627 (( bpp < 24) ? 8 : 24))
1628 );
1629 }
1630
1631 if (!( dc = dc_alloc())) {
1632 if (( Handle) i != img) Object_destroy(( Handle) i);
1633 return NULL;
1634 }
1635
1636 if (!notAnIcon && i->maskType == 8) {
1637 /* argb icon */
1638 int j, size;
1639 void *mask;
1640 Byte * argb;
1641 XBITMAPINFO bi;
1642 image_fill_bitmap_info(( Handle)i, &bi, BM_BITMAP);
1643 bi. bmiColors[ 0]. rgbRed = bi. bmiColors[ 0]. rgbGreen = bi. bmiColors[ 0]. rgbBlue = 0;
1644 bi. bmiColors[ 1]. rgbRed = bi. bmiColors[ 1]. rgbGreen = bi. bmiColors[ 1]. rgbBlue = 255;
1645 mask = i->self->convert_mask(img, imbpp1);
1646 ii. hbmMask = CreateDIBitmap( dc, &bi. bmiHeader, CBM_INIT,
1647 mask, ( BITMAPINFO*) &bi, DIB_RGB_COLORS);
1648 free(mask);
1649 if ( ii. hbmMask == NULL ) return false;
1650
1651 if (( ii. hbmColor = image_create_argb_bitmap(( Handle) i , (uint32_t**) &argb )) == NULL ) {
1652 DeleteObject( ii. hbmMask);
1653 return false;
1654 }
1655 /* alpha 0 is treated very strange if all alpha bytes are 0 and there are not a single non-0 byte -
1656 cursor becomes a negative version of itself. Might be a driver bug though */
1657 size = i-> w * i-> h;
1658 for ( j = 0, argb += 3; j < size; j++, argb += 4)
1659 if ( *argb == 0) *argb = 1;
1660 } else {
1661 XBITMAPINFO bi;
1662 Byte * mask;
1663 image_fill_bitmap_info(( Handle)i, &bi, BM_PIXMAP);
1664 if ( bi. bmiHeader. biClrUsed > 0)
1665 bi. bmiHeader. biClrUsed = bi. bmiHeader. biClrImportant = i-> palSize;
1666
1667 if ( !( ii. hbmColor = CreateDIBitmap( dc, &bi. bmiHeader, CBM_INIT,
1668 i-> data, ( BITMAPINFO*) &bi, DIB_RGB_COLORS))) apiErr;
1669 bi. bmiHeader. biBitCount = bi. bmiHeader. biPlanes = 1;
1670 bi. bmiColors[ 0]. rgbRed = bi. bmiColors[ 0]. rgbGreen = bi. bmiColors[ 0]. rgbBlue = 0;
1671 bi. bmiColors[ 1]. rgbRed = bi. bmiColors[ 1]. rgbGreen = bi. bmiColors[ 1]. rgbBlue = 255;
1672
1673 if ( notAnIcon )
1674 mask = NULL;
1675 else
1676 mask = i-> mask;
1677 if ( !( ii. hbmMask = CreateDIBitmap( dc, &bi. bmiHeader, CBM_INIT,
1678 mask, ( BITMAPINFO*) &bi, DIB_RGB_COLORS))) apiErr;
1679 }
1680
1681 dc_free();
1682
1683 if ( !( r = CreateIconIndirect( &ii))) apiErr;
1684
1685 DeleteObject( ii. hbmColor);
1686 DeleteObject( ii. hbmMask);
1687 if (( Handle) i != img) Object_destroy(( Handle) i);
1688 return r;
1689 }
1690
1691 void *
image_create_dib(Handle image,Bool global_alloc)1692 image_create_dib(Handle image, Bool global_alloc)
1693 {
1694 int size, offset;
1695 XBITMAPINFO bi;
1696 PIcon i;
1697 void *ptr, *ret;
1698 Byte * data;
1699
1700 i = (PIcon) image;
1701 if ( dsys(image)options.aptIcon && i->type != imRGB ) {
1702 Handle dup = CImage(image)->dup(image);
1703 CImage(dup)->set_type( dup, imRGB );
1704 ret = image_create_dib(dup, global_alloc);
1705 Object_destroy(dup);
1706 return ret;
1707 } else if ( i->type & (imSignedInt | imRealNumber | imComplexNumber | imTrigComplexNumber)) {
1708 Handle dup = CImage(image)->dup(image);
1709 CImage(dup)->set_type( dup, imByte );
1710 ret = image_create_dib(dup, global_alloc);
1711 Object_destroy(dup);
1712 return ret;
1713 }
1714
1715 image_fill_bitmap_info(image, &bi, BM_AUTO);
1716 if ( bi.bmiHeader.biClrUsed > 0)
1717 bi.bmiHeader.biClrUsed = bi.bmiHeader.biClrImportant = i-> palSize;
1718
1719 offset = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * bi.bmiHeader.biClrUsed;
1720 size = i->dataSize + sizeof(BITMAPINFOHEADER) + offset;
1721 if ( global_alloc ) {
1722 if (!( ret = GlobalAlloc( GMEM_DDESHARE, size)))
1723 return NULL;
1724 if ( !( ptr = GlobalLock( ret))) {
1725 GlobalFree( ret );
1726 return NULL;
1727 }
1728 } else {
1729 if ( !( ptr = ret = malloc(size)))
1730 return NULL;
1731 }
1732
1733 memcpy( ptr, &bi, offset);
1734 data = ptr;
1735 data += offset;
1736
1737 if ( bi. bmiHeader. biBitCount == 32 ) {
1738 if ( !icon2argb(i, (uint32_t*)data)) {
1739 if ( global_alloc ) {
1740 GlobalUnlock( ret );
1741 GlobalFree( ret );
1742 } else
1743 free(ret);
1744 return NULL;
1745 }
1746 } else
1747 memcpy( data, i->data, i->dataSize );
1748
1749 if ( global_alloc )
1750 GlobalUnlock( ret );
1751
1752 return ret;
1753 }
1754
1755 ApiHandle
apc_image_get_handle(Handle self)1756 apc_image_get_handle( Handle self)
1757 {
1758 objCheck 0;
1759 return ( ApiHandle) sys ps;
1760 }
1761
1762 ApiHandle
apc_dbm_get_handle(Handle self)1763 apc_dbm_get_handle( Handle self)
1764 {
1765 objCheck 0;
1766 return ( ApiHandle) sys ps;
1767 }
1768
1769
1770 #ifdef __cplusplus
1771 }
1772 #endif
1773