]> granicus.if.org Git - imagemagick/blob - MagickCore/nt-feature.c
(no commit message)
[imagemagick] / MagickCore / nt-feature.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                                                                             %
7 %                                 N   N  TTTTT                                %
8 %                                 NN  N    T                                  %
9 %                                 N N N    T                                  %
10 %                                 N  NN    T                                  %
11 %                                 N   N    T                                  %
12 %                                                                             %
13 %                                                                             %
14 %                   Windows NT Feature Methods for MagickCore                 %
15 %                                                                             %
16 %                               Software Design                               %
17 %                                 John Cristy                                 %
18 %                                December 1996                                %
19 %                                                                             %
20 %                                                                             %
21 %  Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization      %
22 %  dedicated to making software imaging solutions freely available.           %
23 %                                                                             %
24 %  You may not use this file except in compliance with the License.  You may  %
25 %  obtain a copy of the License at                                            %
26 %                                                                             %
27 %    http://www.imagemagick.org/script/license.php                            %
28 %                                                                             %
29 %  Unless required by applicable law or agreed to in writing, software        %
30 %  distributed under the License is distributed on an "AS IS" BASIS,          %
31 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
32 %  See the License for the specific language governing permissions and        %
33 %  limitations under the License.                                             %
34 %                                                                             %
35 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36 %
37 %
38 */
39 \f
40 /*
41   Include declarations.
42 */
43 #include "MagickCore/studio.h"
44 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
45 #define WIN32_LEAN_AND_MEAN
46 #define VC_EXTRALEAN
47 #include <windows.h>
48 #include "MagickCore/cache.h"
49 #include "MagickCore/colorspace.h"
50 #include "MagickCore/colorspace-private.h"
51 #include "MagickCore/draw.h"
52 #include "MagickCore/exception.h"
53 #include "MagickCore/exception-private.h"
54 #include "MagickCore/image-private.h"
55 #include "MagickCore/memory_.h"
56 #include "MagickCore/monitor.h"
57 #include "MagickCore/monitor-private.h"
58 #include "MagickCore/nt-base.h"
59 #include "MagickCore/nt-base-private.h"
60 #include "MagickCore/pixel-accessor.h"
61 #include "MagickCore/quantum.h"
62 #include "MagickCore/string_.h"
63 #include "MagickCore/token.h"
64 #include "MagickCore/splay-tree.h"
65 #include "MagickCore/utility.h"
66 #include "MagickCore/nt-base-private.h"
67 \f
68 /*
69 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
70 %                                                                             %
71 %                                                                             %
72 %                                                                             %
73 %   C r o p I m a g e T o H B i t m a p                                       %
74 %                                                                             %
75 %                                                                             %
76 %                                                                             %
77 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
78 %
79 %  CropImageToHBITMAP() extracts a specified region of the image and returns
80 %  it as a Windows HBITMAP. While the same functionality can be accomplished by
81 %  invoking CropImage() followed by ImageToHBITMAP(), this method is more
82 %  efficient since it copies pixels directly to the HBITMAP.
83 %
84 %  The format of the CropImageToHBITMAP method is:
85 %
86 %      HBITMAP CropImageToHBITMAP(Image* image,const RectangleInfo *geometry,
87 %        ExceptionInfo *exception)
88 %
89 %  A description of each parameter follows:
90 %
91 %    o image: the image.
92 %
93 %    o geometry: Define the region of the image to crop with members
94 %      x, y, width, and height.
95 %
96 %    o exception: return any errors or warnings in this structure.
97 %
98 */
99 MagickExport void *CropImageToHBITMAP(Image *image,
100   const RectangleInfo *geometry,ExceptionInfo *exception)
101 {
102 #define CropImageTag  "Crop/Image"
103
104   BITMAP
105     bitmap;
106
107   HBITMAP
108     bitmapH;
109
110   HANDLE
111     bitmap_bitsH;
112
113   MagickBooleanType
114     proceed;
115
116   RectangleInfo
117     page;
118
119   register const Quantum
120     *p;
121
122   register RGBQUAD
123     *q;
124
125   RGBQUAD
126     *bitmap_bits;
127
128   ssize_t
129     y;
130
131   /*
132     Check crop geometry.
133   */
134   assert(image != (const Image *) NULL);
135   assert(image->signature == MagickSignature);
136   if (image->debug != MagickFalse)
137     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
138   assert(geometry != (const RectangleInfo *) NULL);
139   assert(exception != (ExceptionInfo *) NULL);
140   assert(exception->signature == MagickSignature);
141   if (((geometry->x+(ssize_t) geometry->width) < 0) ||
142       ((geometry->y+(ssize_t) geometry->height) < 0) ||
143       (geometry->x >= (ssize_t) image->columns) ||
144       (geometry->y >= (ssize_t) image->rows))
145     ThrowImageException(OptionError,"GeometryDoesNotContainImage");
146   page=(*geometry);
147   if ((page.x+(ssize_t) page.width) > (ssize_t) image->columns)
148     page.width=image->columns-page.x;
149   if ((page.y+(ssize_t) page.height) > (ssize_t) image->rows)
150     page.height=image->rows-page.y;
151   if (page.x < 0)
152     {
153       page.width+=page.x;
154       page.x=0;
155     }
156   if (page.y < 0)
157     {
158       page.height+=page.y;
159       page.y=0;
160     }
161
162   if ((page.width == 0) || (page.height == 0))
163     ThrowImageException(OptionError,"GeometryDimensionsAreZero");
164   /*
165     Initialize crop image attributes.
166   */
167   bitmap.bmType         = 0;
168   bitmap.bmWidth        = (LONG) page.width;
169   bitmap.bmHeight       = (LONG) page.height;
170   bitmap.bmWidthBytes   = bitmap.bmWidth * 4;
171   bitmap.bmPlanes       = 1;
172   bitmap.bmBitsPixel    = 32;
173   bitmap.bmBits         = NULL;
174
175   bitmap_bitsH=(HANDLE) GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,page.width*
176     page.height*bitmap.bmBitsPixel);
177   if (bitmap_bitsH == NULL)
178     return(NULL);
179   bitmap_bits=(RGBQUAD *) GlobalLock((HGLOBAL) bitmap_bitsH);
180   if ( bitmap.bmBits == NULL )
181     bitmap.bmBits = bitmap_bits;
182   if ((IssRGBColorspace(image->colorspace) == MagickFalse) &&
183       (IsGrayColorspace(image->colorspace) == MagickFalse))
184     TransformImageColorspace(image,sRGBColorspace,exception);
185   /*
186     Extract crop image.
187   */
188   q=bitmap_bits;
189   for (y=0; y < (ssize_t) page.height; y++)
190   {
191     register ssize_t
192       x;
193
194     p=GetVirtualPixels(image,page.x,page.y+y,page.width,1,exception);
195     if (p == (const Quantum *) NULL)
196       break;
197
198     /* Transfer pixels, scaling to Quantum */
199     for( x=(ssize_t) page.width ; x> 0 ; x-- )
200     {
201       q->rgbRed = ScaleQuantumToChar(GetPixelRed(image,p));
202       q->rgbGreen = ScaleQuantumToChar(GetPixelGreen(image,p));
203       q->rgbBlue = ScaleQuantumToChar(GetPixelBlue(image,p));
204       q->rgbReserved = 0;
205       p+=GetPixelChannels(image);
206       q++;
207     }
208     proceed=SetImageProgress(image,CropImageTag,y,page.height);
209     if (proceed == MagickFalse)
210       break;
211   }
212   if (y < (ssize_t) page.height)
213     {
214       GlobalUnlock((HGLOBAL) bitmap_bitsH);
215       GlobalFree((HGLOBAL) bitmap_bitsH);
216       return((void *) NULL);
217     }
218   bitmap.bmBits=bitmap_bits;
219   bitmapH=CreateBitmapIndirect(&bitmap);
220   GlobalUnlock((HGLOBAL) bitmap_bitsH);
221   GlobalFree((HGLOBAL) bitmap_bitsH);
222   return((void *) bitmapH);
223 }
224 \f
225 /*
226 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
227 %                                                                             %
228 %                                                                             %
229 %                                                                             %
230 %   I s M a g i c k C o n f l i c t                                           %
231 %                                                                             %
232 %                                                                             %
233 %                                                                             %
234 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
235 %
236 %  IsMagickConflict() returns true if the image format conflicts with a logical
237 %  drive (.e.g. X:).
238 %
239 %  The format of the IsMagickConflict method is:
240 %
241 %      MagickBooleanType IsMagickConflict(const char *magick)
242 %
243 %  A description of each parameter follows:
244 %
245 %    o magick: Specifies the image format.
246 %
247 */
248 MagickExport MagickBooleanType NTIsMagickConflict(const char *magick)
249 {
250   MagickBooleanType
251     status;
252
253   assert(magick != (char *) NULL);
254   if (strlen(magick) > 1)
255     return(MagickFalse);
256   status=(GetLogicalDrives() & (1 << ((toupper((int) (*magick)))-'A'))) != 0 ?
257     MagickTrue : MagickFalse;
258   return(status);
259 }
260 \f
261 /*
262 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
263 %                                                                             %
264 %                                                                             %
265 %                                                                             %
266 +   N T G e t T y pe L i s t                                                  %
267 %                                                                             %
268 %                                                                             %
269 %                                                                             %
270 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
271 %
272 %  NTLoadTypeLists() loads a Windows TrueType fonts.
273 %
274 %  The format of the NTLoadTypeLists method is:
275 %
276 %      MagickBooleanType NTLoadTypeLists(SplayTreeInfo *type_list)
277 %
278 %  A description of each parameter follows:
279 %
280 %    o type_list: A linked list of fonts.
281 %
282 */
283 MagickExport MagickBooleanType NTLoadTypeLists(SplayTreeInfo *type_list,
284   ExceptionInfo *exception)
285 {
286   HKEY
287     reg_key = (HKEY) INVALID_HANDLE_VALUE;
288
289   LONG
290     res;
291
292
293   int
294     list_entries = 0;
295
296   char
297     buffer[MaxTextExtent],
298     system_root[MaxTextExtent],
299     font_root[MaxTextExtent];
300
301   DWORD
302     type,
303     system_root_length;
304
305   MagickBooleanType
306     status;
307
308   /*
309     Try to find the right Windows*\CurrentVersion key, the SystemRoot and
310     then the Fonts key
311   */
312   res = RegOpenKeyExA (HKEY_LOCAL_MACHINE,
313     "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_READ, &reg_key);
314   if (res == ERROR_SUCCESS) {
315     system_root_length=sizeof(system_root)-1;
316     res = RegQueryValueExA(reg_key,"SystemRoot",NULL, &type,
317       (BYTE*) system_root, &system_root_length);
318   }
319   if (res != ERROR_SUCCESS) {
320     res = RegOpenKeyExA (HKEY_LOCAL_MACHINE,
321       "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", 0, KEY_READ, &reg_key);
322     if (res == ERROR_SUCCESS) {
323       system_root_length=sizeof(system_root)-1;
324       res = RegQueryValueExA(reg_key,"SystemRoot",NULL, &type,
325         (BYTE*)system_root, &system_root_length);
326     }
327   }
328   if (res == ERROR_SUCCESS)
329     res = RegOpenKeyExA (reg_key, "Fonts",0, KEY_READ, &reg_key);
330   if (res != ERROR_SUCCESS)
331     return(MagickFalse);
332   *font_root='\0';
333   (void) CopyMagickString(buffer,system_root,MaxTextExtent);
334   (void) ConcatenateMagickString(buffer,"\\fonts\\arial.ttf",MaxTextExtent);
335   if (IsPathAccessible(buffer) != MagickFalse)
336     {
337       (void) CopyMagickString(font_root,system_root,MaxTextExtent);
338       (void) ConcatenateMagickString(font_root,"\\fonts\\",MaxTextExtent);
339     }
340   else
341     {
342       (void) CopyMagickString(font_root,system_root,MaxTextExtent);
343       (void) ConcatenateMagickString(font_root,"\\",MaxTextExtent);
344     }
345
346   {
347     TypeInfo
348       *type_info;
349
350     DWORD
351       registry_index = 0,
352       type,
353       value_data_size,
354       value_name_length;
355
356     char
357       value_data[MaxTextExtent],
358       value_name[MaxTextExtent];
359
360     res = ERROR_SUCCESS;
361
362     while (res != ERROR_NO_MORE_ITEMS)
363       {
364         char
365           *family_extent,
366           token[MaxTextExtent],
367           *pos,
368           *q;
369
370         value_name_length = sizeof(value_name) - 1;
371         value_data_size = sizeof(value_data) - 1;
372         res = RegEnumValueA ( reg_key, registry_index, value_name,
373           &value_name_length, 0, &type, (BYTE*)value_data, &value_data_size);
374         registry_index++;
375         if (res != ERROR_SUCCESS)
376           continue;
377         if ( (pos = strstr(value_name, " (TrueType)")) == (char*) NULL )
378           continue;
379         *pos='\0'; /* Remove (TrueType) from string */
380
381         type_info=(TypeInfo *) AcquireMagickMemory(sizeof(*type_info));
382         if (type_info == (TypeInfo *) NULL)
383           ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
384         (void) ResetMagickMemory(type_info,0,sizeof(TypeInfo));
385
386         type_info->path=ConstantString("Windows Fonts");
387         type_info->signature=MagickSignature;
388
389         /* Name */
390         (void) CopyMagickString(buffer,value_name,MaxTextExtent);
391         for(pos = buffer; *pos != 0 ; pos++)
392           if (*pos == ' ')
393             *pos = '-';
394         type_info->name=ConstantString(buffer);
395
396         /* Fullname */
397         type_info->description=ConstantString(value_name);
398
399         /* Format */
400         type_info->format=ConstantString("truetype");
401
402         /* Glyphs */
403         if (strchr(value_data,'\\') != (char *) NULL)
404           (void) CopyMagickString(buffer,value_data,MaxTextExtent);
405         else
406           {
407             (void) CopyMagickString(buffer,font_root,MaxTextExtent);
408             (void) ConcatenateMagickString(buffer,value_data,MaxTextExtent);
409           }
410
411         LocaleLower(buffer);
412         type_info->glyphs=ConstantString(buffer);
413
414         type_info->stretch=NormalStretch;
415         type_info->style=NormalStyle;
416         type_info->weight=400;
417
418         /* Some fonts are known to require special encodings */
419         if ( (LocaleCompare(type_info->name, "Symbol") == 0 ) ||
420              (LocaleCompare(type_info->name, "Wingdings") == 0 ) ||
421              (LocaleCompare(type_info->name, "Wingdings-2") == 0 ) ||
422              (LocaleCompare(type_info->name, "Wingdings-3") == 0 ) )
423           type_info->encoding=ConstantString("AppleRoman");
424
425         family_extent=value_name;
426
427         for (q=value_name; *q != '\0'; )
428           {
429             GetMagickToken(q,(const char **) &q,token);
430             if (*token == '\0')
431               break;
432
433             if (LocaleCompare(token,"Italic") == 0)
434               {
435                 type_info->style=ItalicStyle;
436               }
437
438             else if (LocaleCompare(token,"Oblique") == 0)
439               {
440                 type_info->style=ObliqueStyle;
441               }
442
443             else if (LocaleCompare(token,"Bold") == 0)
444               {
445                 type_info->weight=700;
446               }
447
448             else if (LocaleCompare(token,"Thin") == 0)
449               {
450                 type_info->weight=100;
451               }
452
453             else if ( (LocaleCompare(token,"ExtraLight") == 0) ||
454                       (LocaleCompare(token,"UltraLight") == 0) )
455               {
456                 type_info->weight=200;
457               }
458
459             else if (LocaleCompare(token,"Light") == 0)
460               {
461                 type_info->weight=300;
462               }
463
464             else if ( (LocaleCompare(token,"Normal") == 0) ||
465                       (LocaleCompare(token,"Regular") == 0) )
466               {
467                 type_info->weight=400;
468               }
469
470             else if (LocaleCompare(token,"Medium") == 0)
471               {
472                 type_info->weight=500;
473               }
474
475             else if ( (LocaleCompare(token,"SemiBold") == 0) ||
476                       (LocaleCompare(token,"DemiBold") == 0) )
477               {
478                 type_info->weight=600;
479               }
480
481             else if ( (LocaleCompare(token,"ExtraBold") == 0) ||
482                       (LocaleCompare(token,"UltraBold") == 0) )
483               {
484                 type_info->weight=800;
485               }
486
487             else if ( (LocaleCompare(token,"Heavy") == 0) ||
488                       (LocaleCompare(token,"Black") == 0) )
489               {
490                 type_info->weight=900;
491               }
492
493             else if (LocaleCompare(token,"Condensed") == 0)
494               {
495                 type_info->stretch = CondensedStretch;
496               }
497
498             else if (LocaleCompare(token,"Expanded") == 0)
499               {
500                 type_info->stretch = ExpandedStretch;
501               }
502
503             else if (LocaleCompare(token,"ExtraCondensed") == 0)
504               {
505                 type_info->stretch = ExtraCondensedStretch;
506               }
507
508             else if (LocaleCompare(token,"ExtraExpanded") == 0)
509               {
510                 type_info->stretch = ExtraExpandedStretch;
511               }
512
513             else if (LocaleCompare(token,"SemiCondensed") == 0)
514               {
515                 type_info->stretch = SemiCondensedStretch;
516               }
517
518             else if (LocaleCompare(token,"SemiExpanded") == 0)
519               {
520                 type_info->stretch = SemiExpandedStretch;
521               }
522
523             else if (LocaleCompare(token,"UltraCondensed") == 0)
524               {
525                 type_info->stretch = UltraCondensedStretch;
526               }
527
528             else if (LocaleCompare(token,"UltraExpanded") == 0)
529               {
530                 type_info->stretch = UltraExpandedStretch;
531               }
532
533             else
534               {
535                 family_extent=q;
536               }
537           }
538
539         (void) CopyMagickString(buffer,value_name,family_extent-value_name+1);
540         StripString(buffer);
541         type_info->family=ConstantString(buffer);
542
543         list_entries++;
544         status=AddValueToSplayTree(type_list,ConstantString(type_info->name),
545           type_info);
546         if (status == MagickFalse)
547           (void) ThrowMagickException(exception,GetMagickModule(),
548             ResourceLimitError,"MemoryAllocationFailed","'%s'",type_info->name);
549       }
550   }
551   RegCloseKey ( reg_key );
552   return(MagickTrue);
553 }
554 \f
555 /*
556 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
557 %                                                                             %
558 %                                                                             %
559 %                                                                             %
560 %   I m a g e T o H B i t m a p                                               %
561 %                                                                             %
562 %                                                                             %
563 %                                                                             %
564 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
565 %
566 %  ImageToHBITMAP() creates a Windows HBITMAP from an image.
567 %
568 %  The format of the ImageToHBITMAP method is:
569 %
570 %      HBITMAP ImageToHBITMAP(Image *image,Exceptioninfo *exception)
571 %
572 %  A description of each parameter follows:
573 %
574 %    o image: the image to convert.
575 %
576 */
577 MagickExport void *ImageToHBITMAP(Image *image,ExceptionInfo *exception)
578 {
579   BITMAP
580     bitmap;
581
582   HANDLE
583     bitmap_bitsH;
584
585   HBITMAP
586     bitmapH;
587
588   register ssize_t
589     x;
590
591   register const Quantum
592     *p;
593
594   register RGBQUAD
595     *q;
596
597   RGBQUAD
598     *bitmap_bits;
599
600   size_t
601     length;
602
603   ssize_t
604     y;
605
606   (void) ResetMagickMemory(&bitmap,0,sizeof(bitmap));
607   bitmap.bmType=0;
608   bitmap.bmWidth=(LONG) image->columns;
609   bitmap.bmHeight=(LONG) image->rows;
610   bitmap.bmWidthBytes=4*bitmap.bmWidth;
611   bitmap.bmPlanes=1;
612   bitmap.bmBitsPixel=32;
613   bitmap.bmBits=NULL;
614   length=bitmap.bmWidthBytes*bitmap.bmHeight;
615   bitmap_bitsH=(HANDLE) GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,length);
616   if (bitmap_bitsH == NULL)
617     {
618       char
619         *message;
620
621       message=GetExceptionMessage(errno);
622       (void) ThrowMagickException(exception,GetMagickModule(),
623         ResourceLimitError,"MemoryAllocationFailed","'%s'",message);
624       message=DestroyString(message);
625       return(NULL);
626     }
627   bitmap_bits=(RGBQUAD *) GlobalLock((HGLOBAL) bitmap_bitsH);
628   q=bitmap_bits;
629   if (bitmap.bmBits == NULL)
630     bitmap.bmBits=bitmap_bits;
631   (void) TransformImageColorspace(image,sRGBColorspace,exception);
632   for (y=0; y < (ssize_t) image->rows; y++)
633   {
634     p=GetVirtualPixels(image,0,y,image->columns,1,exception);
635     if (p == (const Quantum *) NULL)
636       break;
637     for (x=0; x < (ssize_t) image->columns; x++)
638     {
639       q->rgbRed=ScaleQuantumToChar(GetPixelRed(image,p));
640       q->rgbGreen=ScaleQuantumToChar(GetPixelGreen(image,p));
641       q->rgbBlue=ScaleQuantumToChar(GetPixelBlue(image,p));
642       q->rgbReserved=0;
643       p+=GetPixelChannels(image);
644       q++;
645     }
646   }
647   bitmap.bmBits=bitmap_bits;
648   bitmapH=CreateBitmapIndirect(&bitmap);
649   if (bitmapH == NULL)
650     {
651       char
652         *message;
653
654       message=GetExceptionMessage(errno);
655       (void) ThrowMagickException(exception,GetMagickModule(),
656         ResourceLimitError,"MemoryAllocationFailed","'%s'",message);
657       message=DestroyString(message);
658     }
659   GlobalUnlock((HGLOBAL) bitmap_bitsH);
660   GlobalFree((HGLOBAL) bitmap_bitsH);
661   return((void *) bitmapH);
662 }
663 \f
664 #endif