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