1 /*
2 stock.c
3
4 Stock objects - pens, brushes, fonts
5 */
6
7 #include "win32\win32guts.h"
8 #ifndef _APRICOT_H_
9 #include "apricot.h"
10 #endif
11 #include "guts.h"
12 #include <ctype.h>
13 #include "Window.h"
14 #include "Image.h"
15 #include "Printer.h"
16
17 #ifdef __cplusplus
18 extern "C" {
19 #endif
20
21
22 #define sys (( PDrawableData)(( PComponent) self)-> sysData)->
23 #define dsys( view) (( PDrawableData)(( PComponent) view)-> sysData)->
24 #define var (( PWidget) self)->
25 #define HANDLE sys handle
26 #define DHANDLE(x) dsys(x) handle
27
28 // Stylus section
29 PDCStylus
stylus_alloc(PStylus data)30 stylus_alloc( PStylus data)
31 {
32 Bool extPen = data-> extPen. actual;
33 PDCStylus ret = ( PDCStylus) hash_fetch( stylusMan, data, sizeof( Stylus) - ( extPen ? 0 : sizeof( EXTPEN)));
34 if ( ret == NULL) {
35 LOGPEN p;
36 LOGBRUSH * b;
37 LOGBRUSH xbrush;
38
39 if ( hash_count( stylusMan) > 128)
40 stylus_clean();
41
42 ret = ( PDCStylus) malloc( sizeof( DCStylus));
43 if ( !ret) return NULL;
44
45 memcpy( &ret-> s, data, sizeof( Stylus));
46 ret-> refcnt = 0;
47 p = ret-> s. pen;
48
49 if ( !extPen) {
50 if ( !( ret-> hpen = CreatePenIndirect( &p))) {
51 apiErr;
52 ret-> hpen = CreatePen( PS_SOLID, 0, 0);
53 }
54 } else {
55 int i, delta = p. lopnWidth. x > 1 ? p. lopnWidth. x - 1 : 0;
56 LOGBRUSH pb;
57 pb. lbStyle = BS_SOLID;
58 pb. lbColor = ret-> s. pen. lopnColor;
59 pb. lbHatch = 0;
60 for ( i = 1; i < ret-> s. extPen. patResource-> dotsCount; i += 2)
61 ret-> s. extPen. patResource-> dotsPtr[ i] += delta;
62 if ( !( ret-> hpen = ExtCreatePen( ret-> s. extPen. style, p. lopnWidth. x, &pb,
63 ret-> s. extPen. patResource-> dotsCount,
64 ret-> s. extPen. patResource-> dotsPtr
65 ))) {
66 apiErr;
67 ret-> hpen = CreatePen( PS_SOLID, 0, 0);
68 }
69 for ( i = 1; i < ret-> s. extPen. patResource-> dotsCount; i += 2)
70 ret-> s. extPen. patResource-> dotsPtr[ i] -= delta;
71 }
72 b = &ret-> s. brush. lb;
73 if ( ret-> s. brush. lb. lbStyle == BS_DIBPATTERNPT) {
74 if ( ret-> s. brush. backColor == ret-> s. pen. lopnColor) {
75 // workaround Win32 bug with mono bitmaps -
76 // if color and backColor are the same, but fill pattern present, backColor
77 // value is ignored by some unknown, but certainly important reason :)
78 xbrush. lbStyle = BS_SOLID;
79 xbrush. lbColor = ret-> s. pen. lopnColor;
80 xbrush. lbHatch = 0;
81 b = &xbrush;
82 } else {
83 int i;
84 for ( i = 0; i < 8; i++) bmiHatch. bmiData[ i * 4] = ret-> s. brush. pattern[ i];
85 bmiHatch. bmiColors[ 0]. rgbRed = ( ret-> s. brush. backColor & 0xFF);
86 bmiHatch. bmiColors[ 0]. rgbGreen = (( ret-> s. brush. backColor >> 8) & 0xFF);
87 bmiHatch. bmiColors[ 0]. rgbBlue = (( ret-> s. brush. backColor >> 16) & 0xFF);
88 bmiHatch. bmiColors[ 1]. rgbRed = ( ret-> s. pen. lopnColor & 0xFF);
89 bmiHatch. bmiColors[ 1]. rgbGreen = (( ret-> s. pen. lopnColor >> 8) & 0xFF);
90 bmiHatch. bmiColors[ 1]. rgbBlue = (( ret-> s. pen. lopnColor >> 16) & 0xFF);
91 }
92 }
93 if ( !( ret-> hbrush = CreateBrushIndirect( b))) {
94 apiErr;
95 ret-> hbrush = CreateSolidBrush( RGB( 255, 255, 255));
96 }
97 hash_store( stylusMan, &ret-> s, sizeof( Stylus) - ( data-> extPen. actual ? 0 : sizeof( EXTPEN)), ret);
98 }
99 ret-> refcnt++;
100 return ret;
101 }
102
103 void
stylus_free(PDCStylus res,Bool permanent)104 stylus_free( PDCStylus res, Bool permanent)
105 {
106 if ( !res || --res-> refcnt > 0) return;
107 if ( !permanent) {
108 res-> refcnt = 0;
109 return;
110 }
111 if ( res-> hpen) DeleteObject( res-> hpen);
112 if ( res-> hbrush) DeleteObject( res-> hbrush);
113 res-> hbrush = NULL;
114 res-> hpen = NULL;
115 hash_delete( stylusMan, &res-> s, sizeof( Stylus) - ( res-> s. extPen. actual ? 0 : sizeof( EXTPEN)), true);
116 }
117
_st_cleaner(PDCStylus s,int keyLen,void * key,void * dummy)118 static Bool _st_cleaner( PDCStylus s, int keyLen, void * key, void * dummy) {
119 if ( s-> refcnt <= 0) stylus_free( s, true);
120 return false;
121 }
122
123 void
stylus_clean()124 stylus_clean()
125 {
126 hash_first_that( stylusMan, _st_cleaner, NULL, NULL, NULL);
127 }
128
129 Bool
stylus_extpenned(PStylus s)130 stylus_extpenned( PStylus s)
131 {
132 if ( s-> pen. lopnWidth. x > 1) {
133 if ( s-> pen. lopnStyle == PS_NULL)
134 return false;
135 return true;
136 } else if ( s-> pen. lopnStyle == PS_USERSTYLE)
137 return true;
138 return false;
139 }
140
141 Bool
stylus_complex(PStylus s,HDC dc)142 stylus_complex( PStylus s, HDC dc)
143 {
144 int rop;
145 if ( s-> brush. lb. lbStyle == BS_DIBPATTERNPT)
146 return true;
147 if (( s-> pen. lopnStyle != PS_SOLID) &&
148 ( s-> pen. lopnStyle != PS_NULL))
149 return true;
150 rop = GetROP2( dc);
151 if (( rop != R2_COPYPEN) &&
152 ( rop != R2_WHITE ) &&
153 ( rop != R2_NOP ) &&
154 ( rop != R2_BLACK )) return true;
155 return false;
156 }
157
158
159 DWORD
stylus_get_extpen_style(PStylus s)160 stylus_get_extpen_style( PStylus s)
161 {
162 return s-> extPen. lineEnd | s-> pen. lopnStyle | s-> extPen. lineJoin | PS_GEOMETRIC;
163 }
164
165 void
stylus_gp_free(PDCGPStylus res,Bool permanent)166 stylus_gp_free( PDCGPStylus res, Bool permanent)
167 {
168 if ( !res || --res-> refcnt > 0) return;
169 if ( !permanent) {
170 res-> refcnt = 0;
171 return;
172 }
173 if ( res-> brush) GdipDeleteBrush( res-> brush);
174 res-> brush = NULL;
175 if ( res-> pen ) GdipDeletePen(res-> pen);
176 res-> pen = NULL;
177 hash_delete( stylusGpMan, &res-> s, sizeof( GPStylus), true);
178 }
179
_gp_cleaner(PDCGPStylus s,int keyLen,void * key,void * dummy)180 static Bool _gp_cleaner( PDCGPStylus s, int keyLen, void * key, void * dummy) {
181 if ( s-> refcnt <= 0) stylus_gp_free( s, true);
182 return false;
183 }
184
185 void
stylus_gp_clean()186 stylus_gp_clean()
187 {
188 hash_first_that( stylusGpMan, _gp_cleaner, nil, nil, nil);
189 }
190
191 static PDCGPStylus
stylus_gp_fetch(GPStylus * key)192 stylus_gp_fetch( GPStylus * key)
193 {
194 PDCGPStylus cached;
195
196 cached = ( PDCGPStylus) hash_fetch( stylusGpMan, key, sizeof(GPStylus));
197
198 if ( cached == NULL ) {
199 if (( cached = malloc(sizeof(DCGPStylus))) == NULL) {
200 warn("Not enough memory");
201 return NULL;
202 }
203 memset( cached, 0, sizeof(DCGPStylus));
204 cached->s = *key;
205 if ( hash_count( stylusGpMan) > 128)
206 stylus_gp_clean();
207 hash_store( stylusGpMan, key, sizeof(GPStylus), cached);
208 }
209
210 return cached;
211 }
212
213 GpBrush*
stylus_gp_alloc(Handle self)214 stylus_gp_alloc(Handle self)
215 {
216 GPStylus key;
217 DCGPStylus *cached;
218 int r,g,b;
219 PStylus s = & sys stylus;
220
221 if ( sys stylusGPResource) {
222 stylus_gp_free( sys stylusGPResource, 0);
223 sys stylusGPResource = NULL;
224 }
225
226 memset(&key, 0, sizeof(key));
227
228 b = (s->pen.lopnColor >> 16) & 0xff;
229 g = (s->pen.lopnColor & 0xff00) >> 8;
230 r = s->pen.lopnColor & 0xff;
231 key.fg = (sys alpha << 24) | (r << 16) | (g << 8) | b;
232 if ( s-> brush. lb. lbStyle != BS_SOLID ) {
233 key.opaque = (sys currentROP2 == ropCopyPut) ? 1 : 0;
234 b = (s->brush.backColor >> 16) & 0xff;
235 g = (s->brush.backColor & 0xff00) >> 8;
236 r = s->brush.backColor & 0xff;
237 key.bg = (sys alpha << 24) | (r << 16) | (g << 8) | b;
238 *key.fill = *sys fillPattern;
239 }
240
241 if ((cached = stylus_gp_fetch(&key)) == NULL)
242 return NULL;
243
244 if ( cached->brush == NULL ) {
245 if ( s-> brush. lb. lbStyle == BS_SOLID ) {
246 GpSolidFill *f;
247 GPCALL GdipCreateSolidFill((ARGB)key.fg, &f);
248 if ( rc ) goto FAIL;
249
250 cached->brush = (GpBrush*)f;
251 } else {
252 GpBitmap * b;
253 GpTexture * t;
254 uint32_t x, y, fp[64], *fpp, bg;
255
256 bg = key.opaque ? key.bg : 0x00000000;
257 for ( y = 0, fpp = fp; y < 8; y++) {
258 Byte src = sys fillPattern[y];
259 for ( x = 0; x < 8; x++)
260 *(fpp++) = (src & ( 1 << x )) ? key.fg : bg;
261 }
262
263 GPCALL GdipCreateBitmapFromScan0( 8, 8, 32, PixelFormat32bppARGB, (BYTE*)fp, &b);
264 apiGPErrCheck;
265 if ( rc ) goto FAIL;
266
267 GPCALL GdipCreateTexture((GpImage*) b, WrapModeTile, &t);
268 apiGPErrCheck;
269 GdipDisposeImage((GpImage*) b);
270 if ( rc ) goto FAIL;
271
272 cached->brush = (GpBrush*) t;
273 }
274 }
275
276 cached-> refcnt++;
277 sys stylusGPResource = cached;
278 return cached;
279
280 FAIL:
281 hash_delete( stylusGpMan, &key, sizeof(key), true);
282 return NULL;
283 }
284
285 void
stylus_change(Handle self)286 stylus_change( Handle self)
287 {
288 PDCStylus p;
289 PDCStylus newP;
290
291 if ( is_apt( aptDCChangeLock)) return;
292 sys stylusFlags &= ~stbGPBrush;
293
294 p = sys stylusResource;
295 newP = stylus_alloc( &sys stylus);
296 if ( p != newP) {
297 sys stylusResource = newP;
298 sys stylusFlags &= stbGPBrush;
299 }
300 stylus_free( p, false);
301 }
302
303 GpPen*
stylus_gp_get_pen(int lineWidth,uint32_t color)304 stylus_gp_get_pen(int lineWidth, uint32_t color)
305 {
306 GPStylus key;
307 PDCGPStylus cached;
308
309 memset( &key, 0, sizeof(key));
310 key.type = GP_SOLID_PEN;
311 key.fg = color;
312 key.opaque = lineWidth;
313 if (( cached = stylus_gp_fetch(&key)) == NULL)
314 return NULL;
315
316 if ( cached->pen == NULL ) {
317 GPCALL GdipCreatePen1(color, lineWidth, UnitPixel, &cached->pen);
318 apiGPErrCheck;
319 if ( rc ) goto FAIL;
320 }
321
322 return cached->pen;
323
324 FAIL:
325 hash_delete( stylusGpMan, &key, sizeof(key), true);
326 return NULL;
327 }
328
329 PPatResource
patres_fetch(unsigned char * pattern,int len)330 patres_fetch( unsigned char * pattern, int len)
331 {
332 int i;
333 PPatResource r = ( PPatResource) hash_fetch( patMan, pattern, len);
334 if ( r)
335 return r;
336
337 r = ( PPatResource) malloc( sizeof( PatResource) + sizeof( DWORD) * len);
338 if ( !r) return &hPatHollow;
339
340 r-> dotsCount = len;
341 r-> dotsPtr = r-> dots;
342 for ( i = 0; i < len; i++) {
343 DWORD x = ( DWORD) pattern[ i];
344 if ( i & 1)
345 x++;
346 else
347 if ( x > 0) x--;
348 r-> dots[ i] = x;
349 }
350 hash_store( patMan, pattern, len, r);
351 return r;
352 }
353
354 UINT
patres_user(unsigned char * pattern,int len)355 patres_user( unsigned char * pattern, int len)
356 {
357 switch ( len) {
358 case 0:
359 return PS_NULL;
360 case 1:
361 return pattern[0] ? PS_SOLID : PS_NULL;
362 default:
363 return PS_USERSTYLE;
364 }
365 }
366
367 // Stylus end
368
369 // Font section
370
371
372 #define FONTHASH_SIZE 563
373 #define FONTIDHASH_SIZE 23
374
375 typedef struct _FontHashNode
376 {
377 struct _FontHashNode *next;
378 struct _FontHashNode *next2;
379 Font key;
380 Font value;
381 } FontHashNode, *PFontHashNode;
382
383 typedef struct _FontHash
384 {
385 PFontHashNode buckets[ FONTHASH_SIZE];
386 } FontHash, *PFontHash;
387
388 static FontHash fontHash;
389 static FontHash fontHashBySize;
390
391 static unsigned long
elf_hash(const char * key,int size,unsigned long h)392 elf_hash( const char *key, int size, unsigned long h)
393 {
394 unsigned long g;
395 if ( size >= 0) {
396 while ( size) {
397 h = ( h << 4) + *key++;
398 if (( g = h & 0xF0000000))
399 h ^= g >> 24;
400 h &= ~g;
401 size--;
402 }
403 } else {
404 while ( *key) {
405 h = ( h << 4) + *key++;
406 if (( g = h & 0xF0000000))
407 h ^= g >> 24;
408 h &= ~g;
409 }
410 }
411 return h;
412 }
413
414 static unsigned long
elf(Font * font,Bool bySize)415 elf( Font * font, Bool bySize)
416 {
417 unsigned long seed = 0;
418 if ( bySize) {
419 seed = elf_hash( (const char*)&font-> width, (char *)(&(font-> name)) - (char *)&(font-> width), seed);
420 seed = elf_hash( font-> name, -1, seed);
421 seed = elf_hash( font-> encoding, -1, seed);
422 seed = elf_hash( (const char*)&font-> size, sizeof( font-> size), seed);
423 } else {
424 seed = elf_hash( (const char*)&font-> height, (char *)(&(font-> name)) - (char *)&(font-> height), seed);
425 seed = elf_hash( font-> name, -1, seed);
426 seed = elf_hash( font-> encoding, -1, seed);
427 }
428 return seed % FONTHASH_SIZE;
429 }
430
431
432 static PFontHashNode
find_node(const PFont font,Bool bySize)433 find_node( const PFont font, Bool bySize)
434 {
435 unsigned long i;
436 PFontHashNode node;
437 int sz;
438
439 if ( font == NULL) return NULL;
440
441 i = elf( font, bySize);
442 if (bySize)
443 node = fontHashBySize. buckets[ i];
444 else
445 node = fontHash. buckets[ i];
446 if ( bySize) {
447 sz = (char *)(&(font-> name)) - (char *)&(font-> width);
448 while ( node != NULL)
449 {
450 if (( memcmp( &(font-> width), &(node-> key. width), sz) == 0) &&
451 ( strcmp( font-> name, node-> key. name) == 0 ) &&
452 ( strcmp( font-> encoding, node-> key. encoding) == 0 ) &&
453 (font-> resolution == node-> key. resolution) &&
454 (font-> size == node-> key. size))
455 return node;
456 node = node-> next2;
457 }
458 } else {
459 sz = (char *)(&(font-> name)) - (char *)&(font-> height);
460 while ( node != NULL)
461 {
462 if (( memcmp( font, &(node-> key), sz) == 0) &&
463 ( strcmp( font-> name, node-> key. name) == 0 )&&
464 (font-> resolution == node-> key. resolution) &&
465 ( strcmp( font-> encoding, node-> key. encoding) == 0 ))
466 return node;
467 node = node-> next;
468 }
469 }
470 return NULL;
471 }
472
473 Bool
add_font_to_hash(const PFont key,const PFont font,Bool addSizeEntry)474 add_font_to_hash( const PFont key, const PFont font, Bool addSizeEntry)
475 {
476 PFontHashNode node;
477 unsigned long i;
478
479 node = ( PFontHashNode) malloc( sizeof( FontHashNode));
480 if ( node == NULL) return false;
481 memcpy( &(node-> key), key, sizeof( Font));
482 memcpy( &(node-> value), font, sizeof( Font));
483 i = elf(key, 0);
484 node-> next = fontHash. buckets[ i];
485 fontHash. buckets[ i] = node;
486 if ( addSizeEntry) {
487 i = elf( key, 1);
488 node-> next2 = fontHashBySize. buckets[ i];
489 fontHashBySize. buckets[ i] = node;
490 }
491 return true;
492 }
493
494 Bool
get_font_from_hash(PFont font,Bool bySize)495 get_font_from_hash( PFont font, Bool bySize)
496 {
497 PFontHashNode node = find_node( font, bySize);
498 if ( node == NULL) return false;
499 *font = node-> value;
500 return true;
501 }
502
503 Bool
create_font_hash(void)504 create_font_hash( void)
505 {
506 memset ( &fontHash, 0, sizeof( FontHash));
507 memset ( &fontHashBySize, 0, sizeof( FontHash));
508 return true;
509 }
510
511 Bool
destroy_font_hash(void)512 destroy_font_hash( void)
513 {
514 PFontHashNode node, node2;
515 int i;
516 for ( i = 0; i < FONTHASH_SIZE; i++)
517 {
518 node = fontHash. buckets[ i];
519 while ( node)
520 {
521 node2 = node;
522 node = node-> next;
523 free( node2);
524 }
525 }
526 create_font_hash(); // just in case...
527 return true;
528 }
529
530
_ft_cleaner(PDCFont f,int keyLen,void * key,void * dummy)531 static Bool _ft_cleaner( PDCFont f, int keyLen, void * key, void * dummy) {
532 if ( f-> refcnt <= 0) font_free( f, true);
533 return false;
534 }
535
536 static int
build_dcfont_key(Font * src,unsigned char * key)537 build_dcfont_key( Font * src, unsigned char * key)
538 {
539 int sz = FONTSTRUCSIZE;
540 char * p;
541 memcpy( key, src, FONTSTRUCSIZE);
542 key += FONTSTRUCSIZE;
543 p = src-> name;
544 while ( *p) {
545 *(key++) = *(p++);
546 sz++;
547 }
548 *(key++) = 0;
549 sz++;
550 p = src-> encoding;
551 while ( *p) {
552 *(key++) = *(p++);
553 sz++;
554 }
555 *(key++) = 0;
556 sz++;
557 return sz;
558 }
559
560 PDCFont
font_alloc(Font * data)561 font_alloc( Font * data)
562 {
563 char key[sizeof(Font)];
564 int keyLen = build_dcfont_key( data, (unsigned char*)key);
565 PDCFont ret = ( PDCFont) hash_fetch( fontMan, key, keyLen);
566
567 if ( ret == NULL) {
568 LOGFONTW logfont;
569 PFont f;
570
571 if ( hash_count( fontMan) > 128)
572 font_clean();
573
574 ret = ( PDCFont) malloc( sizeof( DCFont));
575 if ( !ret) return NULL;
576
577 memcpy( f = &ret-> font, data, sizeof( Font));
578 ret-> refcnt = 0;
579 font_font2logfont( f, &logfont);
580 if ( !( ret-> hfont = CreateFontIndirectW( &logfont))) {
581 LOGFONTW lf;
582 apiErr;
583 memset( &lf, 0, sizeof( lf));
584 ret-> hfont = CreateFontIndirectW( &lf);
585 }
586 keyLen = build_dcfont_key( &ret-> font, (unsigned char*)key);
587 hash_store( fontMan, key, keyLen, ret);
588 }
589 ret-> refcnt++;
590 return ret;
591 }
592
593 void
font_free(PDCFont res,Bool permanent)594 font_free( PDCFont res, Bool permanent)
595 {
596 int keyLen;
597 char key[sizeof(Font)];
598
599 if ( !res || --res-> refcnt > 0) return;
600 if ( !permanent) {
601 res-> refcnt = 0;
602 return;
603 }
604 if ( res-> hfont) {
605 DeleteObject( res-> hfont);
606 res-> hfont = NULL;
607 }
608 keyLen = build_dcfont_key( &res-> font, (unsigned char*)key);
609 hash_delete( fontMan, key, keyLen, true);
610 }
611
612 void
font_change(Handle self,Font * font)613 font_change( Handle self, Font * font)
614 {
615 PDCFont p;
616 PDCFont newP;
617 if ( is_apt( aptDCChangeLock)) return;
618
619 sys alphaArenaFontChanged = true;
620 p = sys fontResource;
621 newP = ( sys fontResource = font_alloc( font));
622 if ( sys alphaArenaStockFont ) {
623 SelectObject( sys alphaArenaDC, sys alphaArenaStockFont );
624 sys alphaArenaFontChanged = true;
625 }
626 font_free( p, false);
627 if ( sys ps)
628 SelectObject( sys ps, newP-> hfont);
629 }
630
631 void
font_clean()632 font_clean()
633 {
634 hash_first_that( fontMan, _ft_cleaner, NULL, NULL, NULL);
635 }
636
637 static char* encodings[] = {
638 "Western",
639 "Windows",
640 "Symbol",
641 "Shift-JIS",
642 "Hangeul",
643 "GB 2312",
644 "Chinese Big 5",
645 "OEM DOS",
646 "Johab",
647 "Hebrew",
648 "Arabic",
649 "Greek",
650 "Turkish",
651 "Vietnamese",
652 "Thai",
653 "Eastern Europe",
654 "Cyrillic",
655 "Mac",
656 "Baltic",
657 NULL
658 };
659
660 static Handle ctx_CHARSET2index[] = {
661 ANSI_CHARSET , 0,
662 DEFAULT_CHARSET , 1,
663 SYMBOL_CHARSET , 2,
664 SHIFTJIS_CHARSET , 3,
665 HANGEUL_CHARSET , 4,
666 GB2312_CHARSET , 5,
667 CHINESEBIG5_CHARSET , 6,
668 OEM_CHARSET , 7,
669 #ifdef JOHAB_CHARSET
670 JOHAB_CHARSET , 8,
671 HEBREW_CHARSET , 9,
672 ARABIC_CHARSET , 10,
673 GREEK_CHARSET , 11,
674 TURKISH_CHARSET , 12,
675 VIETNAMESE_CHARSET , 13,
676 THAI_CHARSET , 14,
677 EASTEUROPE_CHARSET , 15,
678 RUSSIAN_CHARSET , 16,
679 MAC_CHARSET , 17,
680 BALTIC_CHARSET , 18,
681 #endif
682 endCtx
683 };
684
685 #define MASK_CODEPAGE 0x00FF
686 #define MASK_FAMILY 0xFF00
687 #define FF_MASK 0x00F0
688
689 static char *
font_charset2encoding(int charset)690 font_charset2encoding( int charset)
691 {
692 #define SYNCPLEN 7
693 static char buf[ SYNCPLEN * 256], initialized = false;
694 char *str;
695 int index = ctx_remap_end( charset, ctx_CHARSET2index, true);
696 if ( index == endCtx) {
697 charset &= 255;
698 if ( !initialized) {
699 int i;
700 for ( i = 0; i < 256; i++) sprintf( buf + i * SYNCPLEN, "CP-%d", i);
701 initialized = true;
702 }
703 str = buf + charset * SYNCPLEN;
704 } else
705 str = encodings[ index];
706 return str;
707 }
708
709 static int
font_encoding2charset(const char * encoding)710 font_encoding2charset( const char * encoding)
711 {
712 int index = 0;
713 char ** e = encodings;
714
715 if ( !encoding || encoding[0] == 0) return DEFAULT_CHARSET;
716
717 while ( *e) {
718 if ( strcmp( *e, encoding) == 0)
719 return ctx_remap_def( index, ctx_CHARSET2index, false, DEFAULT_CHARSET);
720 index++;
721 e++;
722 }
723 if ( strncmp( encoding, "CP-", 3) == 0) {
724 int i = atoi( encoding + 3);
725 if ( i <= 0 || i > 256) i = DEFAULT_CHARSET;
726 return i;
727 }
728 return DEFAULT_CHARSET;
729 }
730
731 static Bool
utf8_flag_strncpy(char * dst,const WCHAR * src,unsigned int maxlen)732 utf8_flag_strncpy( char * dst, const WCHAR * src, unsigned int maxlen)
733 {
734 int i;
735 Bool is_utf8 = false;
736 for ( i = 0; i < maxlen && src[i] > 0; i++) {
737 if ( src[i] > 0x7f ) {
738 is_utf8 = true;
739 break;
740 }
741 }
742 WideCharToMultiByte(CP_UTF8, 0, src, -1, (LPSTR)dst, 256, NULL, false);
743 return is_utf8;
744 }
745
746 int CALLBACK
fep_register_mapper_fonts(ENUMLOGFONTEXW FAR * e,NEWTEXTMETRICEXW FAR * t,DWORD type,LPARAM _es)747 fep_register_mapper_fonts( ENUMLOGFONTEXW FAR *e, NEWTEXTMETRICEXW FAR *t, DWORD type, LPARAM _es)
748 {
749 char name[LF_FACESIZE + 1];
750 Bool name_is_utf8;
751 unsigned int i, styles[4], pitch;
752 if (type & RASTER_FONTTYPE) return 1;
753
754 if (e-> elfLogFont.lfFaceName[0] == '@') return 1; /* vertical font */
755
756 name_is_utf8 = utf8_flag_strncpy( name, e-> elfLogFont.lfFaceName, LF_FACESIZE);
757 pitch =
758 ((( e-> elfLogFont.lfPitchAndFamily & 3) == DEFAULT_PITCH ) ? fpDefault :
759 ((( e-> elfLogFont.lfPitchAndFamily & 3) == VARIABLE_PITCH) ? fpVariable : fpFixed));
760
761 styles[0] = fsNormal;
762 styles[1] = fsBold;
763 styles[2] = fsItalic;
764 styles[3] = fsBold | fsItalic;
765 for ( i = 0; i < 4; i++) {
766 PFont f;
767
768 if ((f = prima_font_mapper_save_font(name, styles[i])) == NULL)
769 continue;
770
771 f->undef.pitch = 0;
772 f->pitch = pitch;
773 f->undef.vector = 0;
774 f->vector = fvOutline;
775 f->is_utf8.name = name_is_utf8;
776 f->is_utf8.family = utf8_flag_strncpy( f-> family, e-> elfFullName, LF_FULLFACESIZE);
777 }
778 return 1;
779 }
780
781 void
register_mapper_fonts(void)782 register_mapper_fonts(void)
783 {
784 HDC dc;
785 LOGFONTW elf;
786
787 /* MS Shell Dlg is a virtual font, not reported by enum */
788 prima_font_mapper_save_font(guts.windowFont.name, 0);
789
790 if ( !( dc = dc_alloc()))
791 return;
792 memset( &elf, 0, sizeof( elf));
793 elf. lfCharSet = DEFAULT_CHARSET;
794 EnumFontFamiliesExW( dc, &elf, (FONTENUMPROCW) fep_register_mapper_fonts, 0, 0);
795 dc_free();
796 }
797
798 void
reset_system_fonts(void)799 reset_system_fonts(void)
800 {
801 memset( &guts. windowFont, 0, sizeof( Font));
802 strcpy( guts. windowFont. name, DEFAULT_WIDGET_FONT);
803 guts. windowFont. size = DEFAULT_WIDGET_FONT_SIZE;
804 guts. windowFont. undef. width = guts. windowFont. undef. height = guts. windowFont. undef. vector = 1;
805 apc_font_pick( NULL_HANDLE, &guts. windowFont, &guts. windowFont);
806
807 guts. ncmData. cbSize = sizeof( NONCLIENTMETRICSW);
808 if ( !SystemParametersInfoW( SPI_GETNONCLIENTMETRICS, sizeof( NONCLIENTMETRICSW),
809 ( PVOID) &guts. ncmData, 0)) apiErr;
810 font_logfont2font( &guts.ncmData.lfMenuFont, &guts.menuFont, &guts.displayResolution);
811 font_logfont2font( &guts.ncmData.lfMessageFont, &guts.msgFont, &guts.displayResolution);
812 font_logfont2font( &guts.ncmData.lfCaptionFont, &guts.capFont, &guts.displayResolution);
813 }
814
815 void
font_logfont2font(LOGFONTW * lf,Font * f,Point * res)816 font_logfont2font( LOGFONTW * lf, Font * f, Point * res)
817 {
818 TEXTMETRICW tm;
819 HDC dc = dc_alloc();
820 HFONT hf;
821
822 if ( !dc) return;
823 hf = SelectObject( dc, CreateFontIndirectW( lf));
824
825 GetTextMetricsW( dc, &tm);
826 DeleteObject( SelectObject( dc, hf));
827 dc_free();
828
829 if ( !res) res = &guts. displayResolution;
830 bzero( f, sizeof(Font));
831 f-> height = tm. tmHeight;
832 f-> size = ( f-> height - tm. tmInternalLeading) * 72.0 / res-> y + 0.5;
833 f-> width = lf-> lfWidth;
834 f-> direction = (double)(lf-> lfEscapement) / 10.0;
835 f-> vector = (( tm. tmPitchAndFamily & ( TMPF_VECTOR | TMPF_TRUETYPE)) ? fvOutline : fvBitmap);
836 f-> style = 0 |
837 ( lf-> lfItalic ? fsItalic : 0) |
838 ( lf-> lfUnderline ? fsUnderlined : 0) |
839 ( lf-> lfStrikeOut ? fsStruckOut : 0) |
840 (( lf-> lfWeight >= 700) ? fsBold : 0);
841 f-> pitch = ((( lf-> lfPitchAndFamily & 3) == DEFAULT_PITCH) ? fpDefault :
842 ((( lf-> lfPitchAndFamily & 3) == VARIABLE_PITCH) ? fpVariable : fpFixed));
843 strcpy( f-> encoding, font_charset2encoding( lf-> lfCharSet));
844 f-> is_utf8.name = utf8_flag_strncpy( f->name, lf->lfFaceName, LF_FACESIZE);
845 }
846
847 void
font_font2logfont(Font * f,LOGFONTW * lf)848 font_font2logfont( Font * f, LOGFONTW * lf)
849 {
850 lf-> lfHeight = f-> height;
851 lf-> lfWidth = f-> width;
852 lf-> lfEscapement = f-> direction * 10;
853 lf-> lfOrientation = f-> direction * 10;
854 lf-> lfWeight = ( f-> style & fsBold) ? 800 : 400;
855 lf-> lfItalic = ( f-> style & fsItalic) ? 1 : 0;
856 lf-> lfUnderline = 0;
857 lf-> lfStrikeOut = 0;
858 lf-> lfOutPrecision = f-> vector ? OUT_TT_PRECIS : OUT_RASTER_PRECIS;
859 lf-> lfClipPrecision = CLIP_DEFAULT_PRECIS;
860 lf-> lfQuality = PROOF_QUALITY;
861 lf-> lfPitchAndFamily = FF_DONTCARE;
862 lf-> lfCharSet = font_encoding2charset( f-> encoding);
863 MultiByteToWideChar(CP_UTF8, 0, f->name, -1, lf->lfFaceName, LF_FACESIZE);
864 }
865
866 void
font_textmetric2font(TEXTMETRICW * tm,Font * fm,Bool readonly)867 font_textmetric2font( TEXTMETRICW * tm, Font * fm, Bool readonly)
868 {
869 if ( !readonly) {
870 fm-> size = ( tm-> tmHeight - tm-> tmInternalLeading) * 72.0 / guts. displayResolution.y + 0.5;
871 fm-> width = tm-> tmAveCharWidth;
872 fm-> height = tm-> tmHeight;
873 fm-> style = 0 |
874 ( tm-> tmItalic ? fsItalic : 0) |
875 ( tm-> tmUnderlined ? fsUnderlined : 0) |
876 ( tm-> tmStruckOut ? fsStruckOut : 0) |
877 (( tm-> tmWeight >= 700) ? fsBold : 0)
878 ;
879 }
880 fm-> pitch = (( tm-> tmPitchAndFamily & TMPF_FIXED_PITCH) ? fpVariable : fpFixed);
881 fm-> vector = (( tm-> tmPitchAndFamily & ( TMPF_VECTOR | TMPF_TRUETYPE)) ? true : false);
882 fm-> weight = tm-> tmWeight / 100;
883 fm-> ascent = tm-> tmAscent;
884 fm-> descent = tm-> tmDescent;
885 fm-> maximalWidth = tm-> tmMaxCharWidth;
886 fm-> internalLeading = tm-> tmInternalLeading;
887 fm-> externalLeading = tm-> tmExternalLeading;
888 fm-> xDeviceRes = tm-> tmDigitizedAspectX;
889 fm-> yDeviceRes = tm-> tmDigitizedAspectY;
890 fm-> firstChar = tm-> tmFirstChar;
891 fm-> lastChar = tm-> tmLastChar;
892 fm-> breakChar = tm-> tmBreakChar;
893 fm-> defaultChar = tm-> tmDefaultChar;
894 strcpy( fm-> encoding, font_charset2encoding( tm-> tmCharSet));
895 }
896
897 void
font_pp2font(char * presParam,Font * f)898 font_pp2font( char * presParam, Font * f)
899 {
900 int i;
901 char * p = strchr( presParam, '.');
902
903 memset( f, 0, sizeof( Font));
904 if ( p) {
905 f-> size = atoi( presParam);
906 p++;
907 } else
908 f-> size = 10;
909
910 strncpy( f-> name, p, 255);
911 p = f-> name;
912 f-> style = 0;
913 f-> pitch = fpDefault;
914 for ( i = strlen( p) - 1; i >= 0; i--) {
915 if ( p[ i] == '.') {
916 if ( stricmp( "Italic", &p[ i + 1]) == 0) f-> style |= fsItalic;
917 if ( stricmp( "Bold", &p[ i + 1]) == 0) f-> style |= fsBold;
918 if ( stricmp( "Underscore",&p[ i + 1]) == 0) f-> style |= fsUnderlined;
919 if ( stricmp( "StrikeOut", &p[ i + 1]) == 0) f-> style |= fsStruckOut;
920 p[ i] = 0;
921 }
922 }
923 f-> undef. width = f-> undef. height = f-> undef. vector = 1;
924 f-> direction = 0;
925 }
926
927 PFont
apc_font_default(PFont font)928 apc_font_default( PFont font)
929 {
930 *font = guts. windowFont;
931 font-> pitch = fpDefault;
932 font-> vector = fvDefault;
933 return font;
934 }
935
936 int
apc_font_load(Handle self,char * filename)937 apc_font_load( Handle self, char* filename)
938 {
939 int ret = AddFontResource(( LPCTSTR) filename );
940 if (ret) hash_store( myfontMan, filename, strlen(filename), (void*)NULL);
941 return ret;
942 }
943
944 static Bool recursiveFF = 0;
945 static Bool recursiveFFEncoding = 0;
946 static Bool recursiveFFPitch = 0;
947
948 typedef struct _FEnumStruc
949 {
950 int count;
951 int passedCount;
952 int resValue;
953 int heiValue;
954 int widValue;
955 int fType;
956 Bool useWidth;
957 Bool wantOutline;
958 Bool useVector;
959 Bool usePitch;
960 Bool forceSize;
961 Bool vecId;
962 Bool matchILead;
963 PFont font;
964 TEXTMETRICW tm;
965 LOGFONTW lf;
966 Point res;
967 char name[ LF_FACESIZE];
968 char family[ LF_FULLFACESIZE];
969 Bool is_utf8_name;
970 Bool is_utf8_family;
971 } FEnumStruc, *PFEnumStruc;
972
973 int CALLBACK
fep(ENUMLOGFONTEXW FAR * e,NEWTEXTMETRICEXW FAR * t,DWORD type,LPARAM _es)974 fep( ENUMLOGFONTEXW FAR *e, NEWTEXTMETRICEXW FAR *t, DWORD type, LPARAM _es)
975 {
976 int ret = 1, copy = 0;
977 long hei, res;
978 PFEnumStruc es = (PFEnumStruc) _es;
979 Font * font = es-> font;
980
981 es-> passedCount++;
982
983 if ( es-> usePitch)
984 {
985 int fpitch = ( t-> ntmTm. tmPitchAndFamily & TMPF_FIXED_PITCH) ? fpVariable : fpFixed;
986 if ( fpitch != font-> pitch)
987 return 1; // so this font cannot be selected due pitch pickup failure
988 }
989
990 if ( font-> vector != fvDefault) {
991 int fvector = (( t-> ntmTm. tmPitchAndFamily & ( TMPF_VECTOR | TMPF_TRUETYPE)) ? fvOutline : fvBitmap);
992 if ( fvector != font-> vector)
993 return 1; // so this font cannot be selected due quality pickup failure
994 }
995
996 if ( type & TRUETYPE_FONTTYPE) {
997 copy = 1;
998 es-> vecId = 1;
999 ret = 0; // enough; no further enumeration requred, since Win renders TrueType quite good
1000 // to not mix these with raster fonts.
1001 goto EXIT;
1002 } else if ( !( type & RASTER_FONTTYPE)) {
1003 copy = 1;
1004 ret = 1; // it's vector font; but keep enumeration in case we'll get better match
1005 es-> vecId = 1;
1006 goto EXIT;
1007 }
1008
1009 // bitmapped fonts:
1010 // determining best match for primary measure - size or height
1011 if ( es-> forceSize) {
1012 long xs = ( t-> ntmTm. tmHeight - ( es-> matchILead ? t-> ntmTm. tmInternalLeading : 0))
1013 * 72.0 / es-> res. y + 0.5;
1014 hei = ( xs - font-> size) * ( xs - font-> size);
1015 } else {
1016 long dv = t-> ntmTm. tmHeight - font-> height - ( es-> matchILead ? 0 : t-> ntmTm. tmInternalLeading);
1017 hei = dv * dv;
1018 }
1019
1020 // resolution difference
1021 res = ( t-> ntmTm. tmDigitizedAspectY - es-> res. y) * ( t-> ntmTm. tmDigitizedAspectY - es-> res. y);
1022
1023 if ( hei < es-> heiValue) {
1024 // current height is closer than before...
1025 es-> heiValue = hei;
1026 es-> resValue = res;
1027 if ( es-> useWidth)
1028 es-> widValue = ( e-> elfLogFont. lfWidth - font-> width) * ( e-> elfLogFont. lfWidth - font-> width);
1029 copy = 1;
1030 } else if ( es-> useWidth && ( hei == es-> heiValue)) {
1031 // height is same close, but width is requested and close that before
1032 long wid = ( e-> elfLogFont. lfWidth - font-> width) * ( e-> elfLogFont. lfWidth - font-> width);
1033 if ( wid < es-> widValue) {
1034 es-> widValue = wid;
1035 es-> resValue = res;
1036 copy = 1;
1037 } else if (( wid == es-> widValue) && ( res < es-> resValue)) {
1038 // height and width are same close, but resolution is closer
1039 es-> resValue = res;
1040 copy = 1;
1041 }
1042 } else if (( res < es-> resValue) && ( hei == es-> heiValue)) {
1043 // height is same close, but resolution is closer
1044 es-> resValue = res;
1045 copy = 1;
1046 }
1047
1048 EXIT:
1049
1050 if ( copy) {
1051 es-> count++;
1052 es-> fType = type;
1053 memcpy( &es-> tm, &t-> ntmTm, sizeof( TEXTMETRICW));
1054 es->is_utf8_name = utf8_flag_strncpy( es-> family, e-> elfFullName, LF_FULLFACESIZE);
1055 memcpy( &es-> lf, &e-> elfLogFont, sizeof( LOGFONT));
1056 es->is_utf8_family = utf8_flag_strncpy( es-> name, e-> elfLogFont.lfFaceName, LF_FACESIZE);
1057 wcsncpy( es-> lf.lfFaceName, e-> elfLogFont.lfFaceName, LF_FACESIZE);
1058 }
1059
1060 return ret;
1061 }
1062
1063 static int
1064 font_font2gp( PFont font, Point res, Bool forceSize, HDC dc);
1065
1066 static void
font_logfont2textmetric(HDC dc,LOGFONTW * lf,TEXTMETRICW * tm)1067 font_logfont2textmetric( HDC dc, LOGFONTW * lf, TEXTMETRICW * tm)
1068 {
1069 HFONT hf = SelectObject( dc, CreateFontIndirectW( lf));
1070 GetTextMetricsW( dc, tm);
1071 DeleteObject( SelectObject( dc, hf));
1072 }
1073
1074 int
font_font2gp_internal(PFont font,Point res,Bool forceSize,HDC theDC)1075 font_font2gp_internal( PFont font, Point res, Bool forceSize, HDC theDC)
1076 {
1077 #define out( retVal) if ( !theDC) dc_free(); return retVal
1078 FEnumStruc es;
1079 HDC dc = theDC ? theDC : dc_alloc();
1080 Bool useNameSubplacing = false;
1081 LOGFONTW elf;
1082
1083 if ( !dc) return fvBitmap;
1084
1085 memset( &es, 0, sizeof( es));
1086 es. resValue = es. heiValue = es. widValue = INT_MAX;
1087 es. useWidth = font-> width != 0;
1088 es. useVector = font->vector != fvDefault;
1089 es. wantOutline = (font-> vector == fvDefault && fabs(font-> direction) > 0.0001) || font->vector == fvOutline;
1090 es. usePitch = font-> pitch != fpDefault;
1091 es. res = res;
1092 es. forceSize = forceSize;
1093 es. font = font;
1094 es. matchILead = forceSize ? ( font-> size >= 0) : ( font-> height >= 0);
1095
1096 useNameSubplacing = es. usePitch || es. useVector;
1097 if ( font-> height < 0) font-> height *= -1;
1098 if ( font-> size < 0) font-> size *= -1;
1099
1100 MultiByteToWideChar(CP_UTF8, 0, font->name, -1, elf.lfFaceName, LF_FACESIZE);
1101 elf. lfPitchAndFamily = 0;
1102 elf. lfCharSet = font_encoding2charset( font-> encoding);
1103 EnumFontFamiliesExW( dc, &elf, (FONTENUMPROCW) fep, ( LPARAM) &es, 0);
1104
1105 // check encoding match
1106 if (( es. passedCount == 0) && ( elf. lfCharSet != DEFAULT_CHARSET) && ( recursiveFFEncoding == 0)) {
1107 int r;
1108 font-> name[0] = 0; // any name
1109 recursiveFFEncoding++;
1110 r = font_font2gp_internal( font, res, forceSize, dc);
1111 recursiveFFEncoding--;
1112 out( r);
1113 }
1114
1115 // checking matched font, if available
1116 if ( es. count > 0) {
1117 if ( es. wantOutline) {
1118 if ( !es. vecId) useNameSubplacing = 1; // try other font if bitmap wouldn't fit
1119 es. resValue = es. heiValue = INT_MAX; // cancel bitmap font selection
1120 }
1121
1122 // special synthesized GDI font case
1123 if (
1124 es. useWidth && ( es. widValue > 0) &&
1125 ( es. heiValue == 0) &&
1126 ( es. fType & RASTER_FONTTYPE) &&
1127 ( font-> style & fsBold)
1128 ) {
1129 int r;
1130 Font xf = *font;
1131 xf. width--;
1132 xf. style = 0; // any style could affect tmOverhang
1133 r = font_font2gp( &xf, res, forceSize, dc);
1134 if (( r == fvBitmap) && ( xf. width < font-> width)) {
1135 LOGFONTW lpf;
1136 TEXTMETRICW tm;
1137 font_font2logfont( &xf, &lpf);
1138 lpf. lfWeight = 700;
1139 font_logfont2textmetric( dc, &lpf, &tm);
1140 if ( xf. width + tm. tmOverhang == font-> width) {
1141 font_textmetric2font( &tm, font, true);
1142 font-> direction = 0;
1143 font-> size = xf. size;
1144 font-> height = xf. height;
1145 font-> maximalWidth += tm. tmOverhang;
1146 out( fvBitmap);
1147 }
1148 }
1149 }
1150
1151 // have resolution ok? so using raster font mtx
1152 if (
1153 ( es. heiValue < 2) &&
1154 ( es. fType & RASTER_FONTTYPE) &&
1155 ( !es. useWidth || (( es. widValue == 0) && ( es. heiValue == 0)))
1156 )
1157 {
1158 font-> height = es. tm. tmHeight;
1159 // if synthesized embolding added, we have to reflect that...
1160 // ( 'cos it increments B-extent of a char cell).
1161 if ( font-> style & fsBold) {
1162 LOGFONTW lpf = es. lf;
1163 TEXTMETRICW tm;
1164 lpf. lfWeight = 700; // ignore italics, it changes tmOverhang also
1165 font_logfont2textmetric( dc, &lpf, &tm);
1166 es. tm. tmMaxCharWidth += tm. tmOverhang;
1167 es. lf. lfWidth += tm. tmOverhang;
1168 }
1169 font_textmetric2font( &es. tm, font, true);
1170 font-> direction = 0;
1171 strncpy( font-> family, es. family, LF_FULLFACESIZE);
1172 font-> is_utf8.family = es.is_utf8_family;
1173 font-> size = ( es. tm. tmHeight - es. tm. tmInternalLeading) * 72.0 / res.y + 0.5;
1174 font-> width = es. lf. lfWidth;
1175 out( fvBitmap);
1176 }
1177
1178 // or vector font - for any purpose?
1179 // if so, it could guaranteed that font-> height == tmHeight
1180 if ( es. vecId) {
1181 LOGFONTW lpf = es. lf;
1182 TEXTMETRICW tm;
1183
1184 // since proportional computation of small items as InternalLeading
1185 // gives incorrect result, querying the only valid source - GetTextMetrics
1186 if ( forceSize) {
1187 lpf. lfHeight = font-> size * res. y / 72.0 + 0.5;
1188 if ( es. matchILead) lpf. lfHeight *= -1;
1189 } else
1190 lpf. lfHeight = es. matchILead ? font-> height : -font-> height;
1191
1192 lpf. lfWidth = es. useWidth ? font-> width : 0;
1193
1194 font_logfont2textmetric( dc, &lpf, &tm);
1195 if ( forceSize)
1196 font-> height = tm. tmHeight;
1197 else
1198 font-> size = ( tm. tmHeight - tm. tmInternalLeading) * 72.0 / res. y + 0.5;
1199
1200 if ( !es. useWidth)
1201 font-> width = tm. tmAveCharWidth;
1202
1203 font_textmetric2font( &tm, font, true);
1204 strncpy( font-> family, es. family, LF_FULLFACESIZE);
1205 font-> is_utf8.family = es.is_utf8_family;
1206 out( fvOutline);
1207 }
1208 }
1209
1210 // if strict match not found, use subplacing
1211 if ( useNameSubplacing && recursiveFFPitch == 0)
1212 {
1213 int ret;
1214 int ogp = font-> pitch;
1215
1216 if ( es. usePitch && es. useVector ) {
1217 // is this too much? try first without vector
1218 font-> vector = fvDefault;
1219 ret = font_font2gp( font, res, forceSize, dc);
1220 out(ret);
1221 }
1222
1223 // setting some other( maybe other) font name
1224 if ( es. usePitch) {
1225 switch ( font->pitch ) {
1226 case fpFixed:
1227 strcpy( font-> name, guts. defaultFixedFont);
1228 break;
1229 case fpVariable:
1230 strcpy( font-> name, guts. defaultVariableFont);
1231 break;
1232 }
1233 font-> pitch = fpDefault;
1234 }
1235
1236 if ( es. useVector )
1237 font-> vector = fvDefault;
1238
1239 recursiveFFPitch++;
1240 ret = font_font2gp( font, res, forceSize, dc);
1241 // if that alternative match succeeded with name subplaced again, skip
1242 // that result and use DEFAULT_SYSTEM_FONT match
1243 if (( ogp == fpFixed) && ( strcmp( font-> name, guts. defaultFixedFont) != 0)) {
1244 strcpy( font-> name, DEFAULT_SYSTEM_FONT);
1245 font-> pitch = fpDefault;
1246 ret = font_font2gp( font, res, forceSize, dc);
1247 }
1248 recursiveFFPitch--;
1249 out( ret);
1250 }
1251
1252 // font not found, so use general representation for height and width
1253 strcpy( font-> name, guts. defaultSystemFont);
1254 if ( recursiveFF == 0)
1255 {
1256 // trying to catch default font with correct values
1257 int r;
1258 recursiveFF++;
1259 r = font_font2gp( font, res, forceSize, dc);
1260 recursiveFF--;
1261 out( r);
1262 } else {
1263 int r;
1264 // if not succeeded, to avoid recursive call use "wild guess".
1265 // This could be achieved if system does not have "System" font
1266 *font = guts. windowFont;
1267 font-> pitch = fpDefault;
1268 recursiveFF++;
1269 r = ( recursiveFF < 3) ? font_font2gp( font, res, forceSize, dc) : fvBitmap;
1270 recursiveFF--;
1271 out( r);
1272 }
1273 return fvBitmap;
1274 #undef out
1275 }
1276
1277 static int
font_font2gp(PFont font,Point res,Bool forceSize,HDC dc)1278 font_font2gp( PFont font, Point res, Bool forceSize, HDC dc)
1279 {
1280 Font key;
1281 Bool addSizeEntry;
1282 font-> resolution = res. y * 0x10000 + res. x;
1283 if ( get_font_from_hash( font, forceSize))
1284 return font->vector;
1285 memcpy( &key, font, sizeof( Font));
1286 font_font2gp_internal( font, res, forceSize, dc);
1287 font-> resolution = res. y * 0x10000 + res. x;
1288 if ( forceSize) {
1289 key. height = font-> height;
1290 addSizeEntry = true;
1291 } else {
1292 key. size = font-> size;
1293 addSizeEntry = (font->vector > fvBitmap) ? (( key. height == key. width) || ( key. width == 0)) : true;
1294 }
1295 add_font_to_hash( &key, font, addSizeEntry);
1296 return font->vector;
1297 }
1298
1299 Bool
apc_font_pick(Handle self,PFont source,PFont dest)1300 apc_font_pick( Handle self, PFont source, PFont dest)
1301 {
1302 if ( self) objCheck false;
1303 font_font2gp( dest, apc_gp_get_resolution(self),
1304 Drawable_font_add( self, source, dest), self ? sys ps : 0);
1305 return true;
1306 }
1307
1308 typedef struct {
1309 List lst;
1310 PHash hash;
1311 } Fep2;
1312
1313 int CALLBACK
fep2(ENUMLOGFONTEXW FAR * e,NEWTEXTMETRICEXW FAR * t,DWORD type,LPARAM _f)1314 fep2( ENUMLOGFONTEXW FAR *e, NEWTEXTMETRICEXW FAR *t, DWORD type, LPARAM _f)
1315 {
1316 PFont fm;
1317 char name[256];
1318 Fep2 *f = (Fep2*) _f;
1319 Bool name_is_utf8;
1320
1321 if ( e-> elfLogFont.lfFaceName[0] == '@') return 1; /* skip vertical fonts */
1322
1323 name_is_utf8 = utf8_flag_strncpy( name, e-> elfLogFont.lfFaceName, LF_FACESIZE);
1324
1325 if ( f-> hash) { /* gross-family enumeration */
1326 fm = hash_fetch( f-> hash, name, strlen( name));
1327 if ( fm) {
1328 char ** enc = (char**) fm-> encoding;
1329 unsigned char * shift = (unsigned char*)enc + sizeof(char *) - 1;
1330 if ( *shift + 2 < 256 / sizeof(char*)) {
1331 *(enc + ++(*shift)) = font_charset2encoding( e-> elfLogFont. lfCharSet);
1332 }
1333 return 1;
1334 }
1335 }
1336 fm = ( PFont) malloc( sizeof( Font));
1337 if ( !fm) return 1;
1338 memset( fm, 0, sizeof(Font));
1339 font_textmetric2font(( TEXTMETRICW*) &t-> ntmTm, fm, false);
1340 if ( f-> hash) { /* multi-encoding format */
1341 char ** enc = (char**) fm-> encoding;
1342 unsigned char * shift = (unsigned char*)enc + sizeof(char *) - 1;
1343 memset( fm-> encoding, 0, 256);
1344 *(enc + ++(*shift)) = font_charset2encoding( e-> elfLogFont. lfCharSet); /* lfCharSet is A/W-safe */
1345 hash_store( f-> hash, name, strlen( name), fm);
1346 }
1347 fm-> direction = fm-> resolution = 0;
1348 fm-> is_utf8.name = name_is_utf8;
1349 strcpy( fm-> name, name);
1350 fm-> is_utf8.family = utf8_flag_strncpy( fm-> family, e-> elfFullName, LF_FULLFACESIZE);
1351 list_add( &f-> lst, ( Handle) fm);
1352 return 1;
1353 }
1354
1355 PFont
apc_fonts(Handle self,const char * facename,const char * encoding,int * retCount)1356 apc_fonts( Handle self, const char* facename, const char *encoding, int * retCount)
1357 {
1358 PFont fmtx = NULL;
1359 int i;
1360 HDC dc;
1361 Fep2 f;
1362 Bool hasdc = 0;
1363 LOGFONTW elf;
1364 apcErrClear;
1365
1366 *retCount = 0;
1367 if ( self == NULL_HANDLE || self == application) {
1368 if ( !( dc = dc_alloc())) return NULL;
1369 }
1370 else if ( kind_of( self, CPrinter)) {
1371 if ( !is_opt( optInDraw) && !is_opt( optInDrawInfo)) {
1372 hasdc = 1;
1373 CPrinter( self)-> begin_paint_info( self);
1374 }
1375 dc = sys ps;
1376 } else
1377 return NULL;
1378
1379 f. hash = NULL;
1380 if ( !facename && !encoding)
1381 if ( !( f. hash = hash_create()))
1382 return NULL;
1383 list_create( &f. lst, 256, 256);
1384 memset( &elf, 0, sizeof( elf));
1385 MultiByteToWideChar(CP_UTF8, 0, facename ? facename : "", -1, elf.lfFaceName, LF_FACESIZE);
1386 elf. lfCharSet = font_encoding2charset( encoding);
1387 EnumFontFamiliesExW( dc, &elf, (FONTENUMPROCW) fep2, ( LPARAM) &f, 0);
1388 if ( f. hash) {
1389 hash_destroy( f. hash, false);
1390 f. hash = NULL;
1391 }
1392
1393 if ( self == NULL_HANDLE || self == application)
1394 dc_free();
1395 else if ( hasdc)
1396 CPrinter( self)-> end_paint_info( self);
1397
1398 if ( f. lst. count == 0) goto Nothing;
1399 fmtx = ( PFont) malloc( f. lst. count * sizeof( Font));
1400 if ( !fmtx) return NULL;
1401
1402 *retCount = f. lst. count;
1403 for ( i = 0; i < f. lst. count; i++)
1404 memcpy( &fmtx[ i], ( void *) f. lst. items[ i], sizeof( Font));
1405 list_delete_all( &f. lst, true);
1406 Nothing:
1407 list_destroy( &f. lst);
1408 return fmtx;
1409 }
1410
1411
1412 int CALLBACK
fep3(ENUMLOGFONTEXW FAR * e,NEWTEXTMETRICW FAR * t,DWORD type,LPARAM _lst)1413 fep3( ENUMLOGFONTEXW FAR *e, NEWTEXTMETRICW FAR *t, DWORD type, LPARAM _lst)
1414 {
1415 PHash lst = (PHash) _lst;
1416 char * str = font_charset2encoding( e-> elfLogFont. lfCharSet);
1417 hash_store( lst, str, strlen( str), (void*)1);
1418 return 1;
1419 }
1420
1421 PHash
apc_font_encodings(Handle self)1422 apc_font_encodings( Handle self )
1423 {
1424 HDC dc;
1425 PHash lst;
1426 Bool hasdc = 0;
1427 LOGFONTW elf;
1428 apcErrClear;
1429
1430 if ( self == NULL_HANDLE || self == application) {
1431 if ( !( dc = dc_alloc())) return NULL;
1432 }
1433 else if ( kind_of( self, CPrinter)) {
1434 if ( !is_opt( optInDraw) && !is_opt( optInDrawInfo)) {
1435 hasdc = 1;
1436 CPrinter( self)-> begin_paint_info( self);
1437 }
1438 dc = sys ps;
1439 } else
1440 return NULL;
1441
1442 lst = hash_create();
1443 memset( &elf, 0, sizeof( elf));
1444 elf. lfCharSet = DEFAULT_CHARSET;
1445 EnumFontFamiliesExW( dc, &elf, (FONTENUMPROCW) fep3, ( LPARAM) lst, 0);
1446
1447 if ( self == NULL_HANDLE || self == application)
1448 dc_free();
1449 else if ( hasdc)
1450 CPrinter( self)-> end_paint_info( self);
1451
1452 return lst;
1453 }
1454
1455
1456 // Font end
1457 // Colors section
1458
1459
1460 #define stdDisabled COLOR_GRAYTEXT , COLOR_BTNFACE
1461 #define stdHilite COLOR_HIGHLIGHTTEXT , COLOR_HIGHLIGHT
1462 #define std3d COLOR_BTNHIGHLIGHT , COLOR_BTNSHADOW
1463
1464 static Handle buttonScheme[] = {
1465 COLOR_BTNTEXT, COLOR_BTNFACE,
1466 COLOR_BTNTEXT, COLOR_BTNFACE,
1467 COLOR_GRAYTEXT, COLOR_BTNFACE,
1468 std3d
1469 };
1470 static Handle sliderScheme[] = {
1471 COLOR_WINDOWTEXT, COLOR_SCROLLBAR,
1472 COLOR_WINDOWTEXT, COLOR_SCROLLBAR,
1473 stdDisabled,
1474 std3d
1475 };
1476
1477 static Handle dialogScheme[] = {
1478 COLOR_WINDOWTEXT, COLOR_BTNFACE,
1479 COLOR_CAPTIONTEXT, COLOR_ACTIVECAPTION,
1480 COLOR_INACTIVECAPTIONTEXT, COLOR_INACTIVECAPTION,
1481 std3d
1482 };
1483 static Handle staticScheme[] = {
1484 COLOR_WINDOWTEXT, COLOR_BTNFACE,
1485 COLOR_WINDOWTEXT, COLOR_BTNFACE,
1486 stdDisabled,
1487 std3d
1488 };
1489 static Handle editScheme[] = {
1490 COLOR_WINDOWTEXT, COLOR_WINDOW,
1491 stdHilite,
1492 stdDisabled,
1493 std3d
1494 };
1495 static Handle menuScheme[] = {
1496 COLOR_MENUTEXT, COLOR_MENU,
1497 stdHilite,
1498 stdDisabled,
1499 std3d
1500 };
1501
1502 static Handle scrollScheme[] = {
1503 COLOR_WINDOWTEXT, COLOR_BTNFACE,
1504 stdHilite,
1505 stdDisabled,
1506 std3d
1507 };
1508
1509 static Handle windowScheme[] = {
1510 COLOR_WINDOWTEXT, COLOR_BTNFACE,
1511 COLOR_CAPTIONTEXT, COLOR_ACTIVECAPTION,
1512 COLOR_INACTIVECAPTIONTEXT, COLOR_INACTIVECAPTION,
1513 std3d
1514 };
1515 static Handle customScheme[] = {
1516 COLOR_WINDOWTEXT, COLOR_BTNFACE,
1517 stdHilite,
1518 stdDisabled,
1519 std3d
1520 };
1521
1522 static Handle ctx_wc2SCHEME[] =
1523 {
1524 wcButton , ( Handle) &buttonScheme,
1525 wcCheckBox , ( Handle) &buttonScheme,
1526 wcRadio , ( Handle) &buttonScheme,
1527 wcDialog , ( Handle) &dialogScheme,
1528 wcSlider , ( Handle) &sliderScheme,
1529 wcLabel , ( Handle) &staticScheme,
1530 wcInputLine , ( Handle) &editScheme,
1531 wcEdit , ( Handle) &editScheme,
1532 wcListBox , ( Handle) &editScheme,
1533 wcCombo , ( Handle) &editScheme,
1534 wcMenu , ( Handle) &menuScheme,
1535 wcPopup , ( Handle) &menuScheme,
1536 wcScrollBar , ( Handle) &scrollScheme,
1537 wcWindow , ( Handle) &windowScheme,
1538 wcWidget , ( Handle) &customScheme,
1539 endCtx
1540 };
1541
1542
1543 long
remap_color(long clr,Bool toSystem)1544 remap_color( long clr, Bool toSystem)
1545 {
1546 if ( toSystem && ( clr & clSysFlag)) {
1547 long c = clr;
1548 Handle * scheme = ( Handle *) ctx_remap_def( clr & wcMask, ctx_wc2SCHEME, true, ( Handle) &customScheme);
1549 if (( clr = ( clr & ~wcMask)) > clMaxSysColor) clr = clMaxSysColor;
1550 if ( clr == clSet || clr == clInvalid) return 0xFFFFFF;
1551 if ( clr == clClear) return 0;
1552 c = GetSysColor( scheme[( clr & clSysMask) - 1]);
1553 return c;
1554 } else {
1555 PRGBColor cp = ( PRGBColor) &clr;
1556 unsigned char sw = cp-> r;
1557 cp-> r = cp-> b;
1558 cp-> b = sw;
1559 return clr;
1560 }
1561 }
1562
1563 Color
apc_lookup_color(const char * colorName)1564 apc_lookup_color( const char * colorName)
1565 {
1566 char buf[ 256];
1567 char *b;
1568 int len;
1569
1570 #define xcmp( name, stlen, retval) if (( len == stlen) && ( strcmp( name, buf) == 0)) return retval
1571
1572 strncpy( buf, colorName, 255);
1573 len = strlen( buf);
1574 for ( b = buf; *b; b++) *b = tolower(*b);
1575
1576 switch( buf[0]) {
1577 case 'a':
1578 xcmp( "aqua", 4, 0x00FFFF);
1579 xcmp( "azure", 5, ARGB(240,255,255));
1580 break;
1581 case 'b':
1582 xcmp( "black", 5, 0x000000);
1583 xcmp( "blanchedalmond", 14, ARGB( 255,235,205));
1584 xcmp( "blue", 4, 0x000080);
1585 xcmp( "brown", 5, 0x808000);
1586 xcmp( "beige", 5, ARGB(245,245,220));
1587 break;
1588 case 'c':
1589 xcmp( "cyan", 4, 0x008080);
1590 xcmp( "chocolate", 9, ARGB(210,105,30));
1591 break;
1592 case 'd':
1593 xcmp( "darkgray", 8, 0x404040);
1594 break;
1595 case 'e':
1596 break;
1597 case 'f':
1598 xcmp( "fuchsia", 7, 0xFF00FF);
1599 break;
1600 case 'g':
1601 xcmp( "green", 5, 0x008000);
1602 xcmp( "gray", 4, 0x808080);
1603 xcmp( "gray80", 6, ARGB(204,204,204));
1604 xcmp( "gold", 4, ARGB(255,215,0));
1605 break;
1606 case 'h':
1607 xcmp( "hotpink", 7, ARGB(255,105,180));
1608 break;
1609 case 'i':
1610 xcmp( "ivory", 5, ARGB(255,255,240));
1611 break;
1612 case 'j':
1613 break;
1614 case 'k':
1615 xcmp( "khaki", 5, ARGB(240,230,140));
1616 break;
1617 case 'l':
1618 xcmp( "lime", 4, 0x00FF00);
1619 xcmp( "lightgray", 9, 0xC0C0C0);
1620 xcmp( "lightblue", 9, 0x0000FF);
1621 xcmp( "lightgreen", 10, 0x00FF00);
1622 xcmp( "lightcyan", 9, 0x00FFFF);
1623 xcmp( "lightmagenta", 12, 0xFF00FF);
1624 xcmp( "lightred", 8, 0xFF0000);
1625 xcmp( "lemon", 5, ARGB(255,250,205));
1626 break;
1627 case 'm':
1628 xcmp( "maroon", 6, 0x800000);
1629 xcmp( "magenta", 7, 0x800080);
1630 break;
1631 case 'n':
1632 xcmp( "navy", 4, 0x000080);
1633 break;
1634 case 'o':
1635 xcmp( "olive", 5, 0x808000);
1636 xcmp( "orange", 6, ARGB(255,165,0));
1637 break;
1638 case 'p':
1639 xcmp( "purple", 6, 0x800080);
1640 xcmp( "peach", 5, ARGB(255,218,185));
1641 xcmp( "peru", 4, ARGB(205,133,63));
1642 xcmp( "pink", 4, ARGB(255,192,203));
1643 xcmp( "plum", 4, ARGB(221,160,221));
1644 break;
1645 case 'q':
1646 break;
1647 case 'r':
1648 xcmp( "red", 3, 0x800000);
1649 xcmp( "royalblue", 9, ARGB(65,105,225));
1650 break;
1651 case 's':
1652 xcmp( "silver", 6, 0xC0C0C0);
1653 xcmp( "sienna", 6, ARGB(160,82,45));
1654 break;
1655 case 't':
1656 xcmp( "teal", 4, 0x008080);
1657 xcmp( "turquoise", 9, ARGB(64,224,208));
1658 xcmp( "tan", 3, ARGB(210,180,140));
1659 xcmp( "tomato", 6, ARGB(255,99,71));
1660 break;
1661 case 'u':
1662 break;
1663 case 'w':
1664 xcmp( "white", 5, 0xFFFFFF);
1665 xcmp( "wheat", 5, ARGB(245,222,179));
1666 break;
1667 case 'v':
1668 xcmp( "violet", 6, ARGB(238,130,238));
1669 break;
1670 case 'x':
1671 break;
1672 case 'y':
1673 xcmp( "yellow", 6, 0xFFFF00);
1674 break;
1675 case 'z':
1676 break;
1677 }
1678
1679 #undef xcmp
1680
1681 return clInvalid;
1682 }
1683
1684 // Colors end
1685 // Miscellaneous
1686
1687 static HDC cachedScreenDC = NULL;
1688 static int cachedScreenRC = 0;
1689 static HDC cachedCompatDC = NULL;
1690 static int cachedCompatRC = 0;
1691
1692
dc_alloc()1693 HDC dc_alloc()
1694 {
1695 if ( cachedScreenRC++ == 0) {
1696 if ( !( cachedScreenDC = GetDC( 0)))
1697 apiErr;
1698 }
1699 return cachedScreenDC;
1700 }
1701
dc_free()1702 void dc_free()
1703 {
1704 if ( --cachedScreenRC <= 0)
1705 ReleaseDC( 0, cachedScreenDC);
1706 if ( cachedScreenRC < 0)
1707 cachedScreenRC = 0;
1708 }
1709
dc_compat_alloc(HDC compatDC)1710 HDC dc_compat_alloc( HDC compatDC)
1711 {
1712 if ( cachedCompatRC++ == 0) {
1713 if ( !( cachedCompatDC = CreateCompatibleDC( compatDC)))
1714 apiErr;
1715 }
1716 return cachedCompatDC;
1717 }
1718
dc_compat_free()1719 void dc_compat_free()
1720 {
1721 if ( --cachedCompatRC <= 0)
1722 DeleteDC( cachedCompatDC);
1723 if ( cachedCompatRC < 0)
1724 cachedCompatRC = 0;
1725 }
1726
1727 void
hwnd_enter_paint(Handle self)1728 hwnd_enter_paint( Handle self)
1729 {
1730 Point res;
1731 GetObject( sys stockPen = GetCurrentObject( sys ps, OBJ_PEN),
1732 sizeof( LOGPEN), &sys stylus. pen);
1733 GetObject( sys stockBrush = GetCurrentObject( sys ps, OBJ_BRUSH),
1734 sizeof( LOGBRUSH), &sys stylus. brush);
1735 sys stockFont = GetCurrentObject( sys ps, OBJ_FONT);
1736 if ( !sys stockPalette)
1737 sys stockPalette = GetCurrentObject( sys ps, OBJ_PAL);
1738 font_free( sys fontResource, false);
1739 sys stylusResource = NULL;
1740 sys stylusGPResource = NULL;
1741 sys fontResource = NULL;
1742 sys stylusFlags = 0;
1743 sys stylus. extPen. actual = false;
1744 apt_set( aptDCChangeLock);
1745 sys bpp = GetDeviceCaps( sys ps, BITSPIXEL);
1746 if ( is_apt( aptWinPS) && self != application) {
1747 apc_gp_set_color( self, sys viewColors[ ciFore]);
1748 apc_gp_set_back_color( self, sys viewColors[ ciBack]);
1749 } else {
1750 apc_gp_set_color( self, remap_color(sys lbs[0],false));
1751 apc_gp_set_back_color( self, remap_color(sys lbs[1],false));
1752 }
1753
1754 if ( sys psd == NULL) sys psd = ( PPaintSaveData) malloc( sizeof( PaintSaveData));
1755 if ( sys psd == NULL) return;
1756
1757 apc_gp_set_alpha( self, sys alpha);
1758 apc_gp_set_antialias( self, is_apt( aptGDIPlus));
1759 apc_gp_set_text_opaque( self, is_apt( aptTextOpaque));
1760 apc_gp_set_text_out_baseline( self, is_apt( aptTextOutBaseline));
1761 apc_gp_set_fill_mode( self, sys fillMode);
1762 apc_gp_set_fill_pattern_offset( self, sys fillPatternOffset);
1763 apc_gp_set_line_width( self, sys lineWidth);
1764 apc_gp_set_line_end( self, sys lineEnd);
1765 apc_gp_set_line_join( self, sys lineJoin);
1766 apc_gp_set_line_pattern( self,
1767 ( Byte*)(( sys linePatternLen > sizeof(sys linePattern)) ? sys linePattern : ( Byte*)&sys linePattern),
1768 sys linePatternLen);
1769 apc_gp_set_miter_limit( self, sys miterLimit);
1770 apc_gp_set_rop( self, sys rop);
1771 apc_gp_set_rop2( self, sys rop2);
1772 apc_gp_set_transform( self, sys transform. x, sys transform. y);
1773 apc_gp_set_fill_pattern( self, sys fillPattern2);
1774 sys psd-> alpha = sys alpha;
1775 sys psd-> antialias = is_apt( aptGDIPlus);
1776 sys psd-> font = var font;
1777 sys psd-> fillMode = sys fillMode;
1778 sys psd-> fillPatternOffset = sys fillPatternOffset;
1779 sys psd-> lineWidth = sys lineWidth;
1780 sys psd-> lineEnd = sys lineEnd;
1781 sys psd-> lineJoin = sys lineJoin;
1782 sys psd-> linePattern = sys linePattern;
1783 sys psd-> linePatternLen = sys linePatternLen;
1784 sys psd-> rop = sys rop;
1785 sys psd-> rop2 = sys rop2;
1786 sys psd-> transform = sys transform;
1787 sys psd-> textOpaque = is_apt( aptTextOpaque);
1788 sys psd-> textOutB = is_apt( aptTextOutBaseline);
1789 sys psd-> antialias = is_apt( aptGDIPlus);
1790
1791 apt_clear( aptDCChangeLock);
1792 stylus_change( self);
1793 apc_gp_set_font( self, &var font);
1794 res = apc_gp_get_resolution(self);
1795 var font. resolution = res. y * 0x10000 + res. x;
1796 SetStretchBltMode( sys ps, COLORONCOLOR);
1797 }
1798
1799 void
hwnd_leave_paint(Handle self)1800 hwnd_leave_paint( Handle self)
1801 {
1802 if ( sys graphics) {
1803 GdipDeleteGraphics(sys graphics);
1804 sys graphics = NULL;
1805 }
1806 SelectObject( sys ps, sys stockPen);
1807 SelectObject( sys ps, sys stockBrush);
1808 SelectObject( sys ps, sys stockFont);
1809 SelectPalette( sys ps, sys stockPalette, 0);
1810 sys stockPen = NULL;
1811 sys stockBrush = NULL;
1812 sys stockFont = NULL;
1813 sys stockPalette = NULL;
1814 stylus_free( sys stylusResource, false);
1815 if ( sys opaquePen ) {
1816 DeleteObject( sys opaquePen );
1817 sys opaquePen = NULL;
1818 }
1819 if ( sys psd != NULL) {
1820 var font = sys psd-> font;
1821 sys alpha = sys psd-> alpha;
1822 sys fillMode = sys psd-> fillMode;
1823 sys fillPatternOffset = sys psd-> fillPatternOffset;
1824 sys lineWidth = sys psd-> lineWidth;
1825 sys lineEnd = sys psd-> lineEnd;
1826 sys lineJoin = sys psd-> lineJoin;
1827 sys linePattern = sys psd-> linePattern;
1828 sys linePatternLen = sys psd-> linePatternLen;
1829 sys rop = sys psd-> rop;
1830 sys rop2 = sys psd-> rop2;
1831 sys transform = sys psd-> transform;
1832 apt_assign( aptTextOpaque, sys psd-> textOpaque);
1833 apt_assign( aptTextOutBaseline, sys psd-> textOutB);
1834 apt_assign( aptGDIPlus, sys psd-> antialias);
1835 free( sys psd);
1836 sys psd = NULL;
1837 }
1838 sys bpp = 0;
1839 }
1840
1841 Bool
hwnd_repaint_layered(Handle self,Bool now)1842 hwnd_repaint_layered( Handle self, Bool now )
1843 {
1844 Event ev;
1845 Handle top;
1846
1847 top = hwnd_layered_top_level( self );
1848 if ( top && top != self && dsys(top) options. aptLayered )
1849 return hwnd_repaint_layered(top, now);
1850
1851 if ( !is_apt( aptLayered)) return false;
1852
1853 if ( !now && !is_apt( aptSyncPaint) ) {
1854 if ( !is_apt( aptRepaintPending )) {
1855 apt_set( aptRepaintPending );
1856 PostMessage(( HWND) var handle, WM_REPAINT_LAYERED, 0, 0);
1857 }
1858 return false;
1859 }
1860
1861 apt_clear( aptRepaintPending );
1862 ev. cmd = cmPaint;
1863 CWidget(self)-> message( self, &ev);
1864
1865 return true;
1866 }
1867
1868 Handle
hwnd_top_level(Handle self)1869 hwnd_top_level( Handle self)
1870 {
1871 while ( self) {
1872 if ( sys className == WC_FRAME) return self;
1873 self = var owner;
1874 }
1875 return NULL_HANDLE;
1876 }
1877
1878 Handle
hwnd_frame_top_level(Handle self)1879 hwnd_frame_top_level( Handle self)
1880 {
1881 while ( self && ( self != application)) {
1882 if (( sys className == WC_FRAME) ||
1883 ( !is_apt( aptClipOwner) && ( var owner != application))) return self;
1884 self = var owner;
1885 }
1886 return NULL_HANDLE;
1887 }
1888
1889 Handle
hwnd_layered_top_level(Handle self)1890 hwnd_layered_top_level( Handle self)
1891 {
1892 while ( self && ( self != application)) {
1893 if (( sys className == WC_FRAME) ||
1894 (!is_apt( aptClipOwner) || (var owner == application))) return self;
1895 self = var owner;
1896 }
1897 return NULL_HANDLE;
1898 }
1899
1900 typedef struct _ModData
1901 {
1902 BYTE ks [ 256];
1903 BYTE kss [ 3];
1904 BYTE *gks;
1905 } ModData;
1906
1907
1908 BYTE *
mod_select(int mod)1909 mod_select( int mod)
1910 {
1911 ModData * ks;
1912
1913 ks = ( ModData*) malloc( sizeof( ModData));
1914 if ( !ks) return NULL;
1915
1916 GetKeyboardState( ks-> ks);
1917 ks-> kss[ 0] = ks-> ks[ VK_MENU];
1918 ks-> kss[ 1] = ks-> ks[ VK_CONTROL];
1919 ks-> kss[ 2] = ks-> ks[ VK_SHIFT];
1920 ks-> ks[ VK_MENU ] = ( mod & kmAlt ) ? 0x80 : 0;
1921 ks-> ks[ VK_CONTROL] = ( mod & kmCtrl ) ? 0x80 : 0;
1922 ks-> ks[ VK_SHIFT ] = ( mod & kmShift) ? 0x80 : 0;
1923 SetKeyboardState( ks-> ks);
1924 ks-> gks = guts. currentKeyState;
1925 guts. currentKeyState = ks-> ks;
1926 return ( BYTE*) ks;
1927 }
1928
1929 void
mod_free(BYTE * modState)1930 mod_free( BYTE * modState)
1931 {
1932 ModData * ks = ( ModData*) modState;
1933 if ( !ks) return;
1934
1935 ks-> ks[ VK_MENU ] = ks-> kss[ 0];
1936 ks-> ks[ VK_CONTROL] = ks-> kss[ 1];
1937 ks-> ks[ VK_SHIFT ] = ks-> kss[ 2];
1938 SetKeyboardState( ks-> ks);
1939 guts. currentKeyState = ks-> gks;
1940 free( ks);
1941 }
1942
1943 typedef struct _SzList
1944 {
1945 List l;
1946 int sz;
1947 PRGBColor p;
1948 } SzList, *PSzList;
1949
1950 static Bool
pal_count(Handle window,Handle self,PSzList l)1951 pal_count( Handle window, Handle self, PSzList l)
1952 {
1953 if ( !is_apt( aptClipOwner) && ( window != application))
1954 return false;
1955 if ( var palSize > 0) {
1956 list_add( &l->l, self);
1957 l->sz += var palSize;
1958 }
1959 if ( var widgets. count > 0)
1960 CWidget( self)-> first_that( self, pal_count, l);
1961 return false;
1962 }
1963
1964 static Bool
pal_collect(Handle self,PSzList l)1965 pal_collect( Handle self, PSzList l)
1966 {
1967 memcpy( l-> p, var palette, var palSize * sizeof( RGBColor));
1968 l-> p += var palSize;
1969 return false;
1970 }
1971
1972 static Bool
repaint_all(Handle owner,Handle self,void * dummy)1973 repaint_all( Handle owner, Handle self, void * dummy)
1974 {
1975 objCheck false;
1976 if ( !is_apt( aptClipOwner))
1977 return false;
1978 if ( !is_apt( aptTransparent)) {
1979 if ( !InvalidateRect(( HWND) var handle, NULL, false)) apiErr;
1980 if ( is_apt( aptSyncPaint) && !apcUpdateWindow(( HWND) var handle)) apiErr;
1981 objCheck false;
1982 var self-> first_that( self, repaint_all, NULL);
1983 }
1984 process_transparents( self);
1985 return false;
1986 }
1987
1988 void
hwnd_repaint(Handle self)1989 hwnd_repaint( Handle self)
1990 {
1991 objCheck;
1992 if ( !InvalidateRect (( HWND) var handle, NULL, false)) apiErr;
1993 if ( is_apt( aptSyncPaint) && !apcUpdateWindow(( HWND) var handle)) apiErr;
1994 objCheck;
1995 var self-> first_that( self, repaint_all, NULL);
1996 process_transparents( self);
1997 }
1998
1999 Bool
palette_change(Handle self)2000 palette_change( Handle self)
2001 {
2002 SzList l;
2003 PRGBColor p;
2004 PRGBColor d;
2005 int nColors = ( 1 << (
2006 guts. displayBMInfo. bmiHeader. biBitCount *
2007 guts. displayBMInfo. bmiHeader. biPlanes
2008 )) & 0x1FF;
2009 int i;
2010 HPALETTE pal;
2011 XLOGPALETTE xlp = {0x300};
2012 HDC dc;
2013
2014 if ( nColors == 0)
2015 return false;
2016
2017 self = hwnd_frame_top_level( self);
2018 if ( self == NULL_HANDLE) return false;
2019
2020 list_create( &l.l, 32, 32);
2021 l. sz = 0;
2022 if ( var palSize > 0) {
2023 list_add( &l.l, self);
2024 l.sz += var palSize;
2025 }
2026 if ( var widgets. count > 0)
2027 CWidget( self)-> first_that( self, pal_count, &l);
2028
2029 if ( l. l. count == 0) {
2030 list_destroy( &l.l);
2031 hwnd_repaint( self);
2032 return false;
2033 }
2034
2035
2036 xlp. palNumEntries = l. sz;
2037 p = ( PRGBColor) malloc( sizeof( RGBColor) * l. sz);
2038 if ( !p) {
2039 list_destroy( &l.l);
2040 hwnd_repaint( self);
2041 return false;
2042 }
2043
2044 d = ( PRGBColor) malloc( sizeof( RGBColor) * nColors);
2045 if ( !d) {
2046 free( p);
2047 list_destroy( &l.l);
2048 hwnd_repaint( self);
2049 return false;
2050 }
2051
2052 l. p = p;
2053 list_first_that( &l.l, pal_collect, &l);
2054 cm_squeeze_palette( p, xlp. palNumEntries, d, nColors);
2055 xlp. palNumEntries = nColors;
2056
2057 for ( i = 0; i < nColors; i++) {
2058 xlp. palPalEntry[ i]. peRed = d[ i]. r;
2059 xlp. palPalEntry[ i]. peGreen = d[ i]. g;
2060 xlp. palPalEntry[ i]. peBlue = d[ i]. b;
2061 xlp. palPalEntry[ i]. peFlags = 0;
2062 }
2063
2064 free( d);
2065 free( p);
2066
2067 pal = CreatePalette(( LOGPALETTE *) &xlp);
2068
2069 dc = GetDC( HANDLE);
2070 pal = SelectPalette( dc, pal, 0);
2071 RealizePalette( dc);
2072 DeleteObject( SelectPalette( dc, pal, 0));
2073 ReleaseDC( HANDLE, dc);
2074
2075 hwnd_repaint( self);
2076
2077 list_destroy( &l.l);
2078 return true;
2079 }
2080
2081 int
palette_match_color(XLOGPALETTE * lp,long clr,int * diffFactor)2082 palette_match_color( XLOGPALETTE * lp, long clr, int * diffFactor)
2083 {
2084 int diff = 0x10000, cdiff = 0, ret = 0, nCol = lp-> palNumEntries;
2085 RGBColor color;
2086
2087 if ( nCol == 0) {
2088 if ( diffFactor) *diffFactor = 0;
2089 return clr;
2090 }
2091
2092 color. r = clr & 0xFF;
2093 color. g = ( clr >> 8) & 0xFF;
2094 color. b = ( clr >> 16) & 0xFF;
2095
2096 while( nCol--)
2097 {
2098 int dr=abs((int)color. r - (int)lp-> palPalEntry[ nCol]. peRed),
2099 dg=abs((int)color. g - (int)lp-> palPalEntry[ nCol]. peGreen),
2100 db=abs((int)color. b - (int)lp-> palPalEntry[ nCol]. peBlue);
2101 cdiff=dr*dr+dg*dg+db*db;
2102 if ( cdiff < diff) {
2103 ret = nCol;
2104 diff = cdiff;
2105 if ( cdiff == 0) break;
2106 }
2107 }
2108
2109 if ( diffFactor) *diffFactor = cdiff;
2110 return ret;
2111 }
2112
2113
2114 long
palette_match(Handle self,long clr)2115 palette_match( Handle self, long clr)
2116 {
2117 XLOGPALETTE lp;
2118 int cdiff;
2119 RGBColor color;
2120
2121 lp. palNumEntries = GetPaletteEntries( sys pal, 0, 256, lp. palPalEntry);
2122
2123 if ( lp. palNumEntries == 0) {
2124 apiErr;
2125 return clr;
2126 }
2127
2128 color. r = clr & 0xFF;
2129 color. g = ( clr >> 8) & 0xFF;
2130 color. b = ( clr >> 16) & 0xFF;
2131
2132 palette_match_color( &lp, clr, &cdiff);
2133
2134 if ( cdiff >= COLOR_TOLERANCE)
2135 return clr;
2136
2137 lp. palNumEntries = GetSystemPaletteEntries( sys ps, 0, 256, lp. palPalEntry);
2138
2139 palette_match_color( &lp, clr, &cdiff);
2140
2141 if ( cdiff >= COLOR_TOLERANCE)
2142 return clr;
2143
2144 return PALETTERGB( color.r, color.g, color.b);
2145 }
2146
2147 int
arc_completion(double * angleStart,double * angleEnd,int * needFigure)2148 arc_completion( double * angleStart, double * angleEnd, int * needFigure)
2149 {
2150 int max;
2151 long diff = ((long)( fabs( *angleEnd - *angleStart) * 1000 + 0.5));
2152
2153 if ( diff == 0) {
2154 *needFigure = false;
2155 return 0;
2156 }
2157 diff /= 1000;
2158
2159 while ( *angleStart > *angleEnd)
2160 *angleEnd += 360;
2161
2162 while ( *angleStart < 0) {
2163 *angleStart += 360;
2164 *angleEnd += 360;
2165 }
2166
2167 while ( *angleStart >= 360) {
2168 *angleStart -= 360;
2169 *angleEnd -= 360;
2170 }
2171
2172 while ( *angleEnd >= *angleStart + 360)
2173 *angleEnd -= 360;
2174
2175 if ( diff < 360) {
2176 *needFigure = true;
2177 return 0;
2178 }
2179
2180 max = (int)(diff / 360);
2181 *needFigure = ( max * 360) != diff;
2182 return ( max % 2) ? 1 : 2;
2183 }
2184
2185
2186 #ifdef __cplusplus
2187 }
2188 #endif
2189