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