2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14 % Windows NT Feature Methods for MagickCore %
21 % Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
22 % dedicated to making software imaging solutions freely available. %
24 % You may not use this file except in compliance with the License. You may %
25 % obtain a copy of the License at %
27 % http://www.imagemagick.org/script/license.php %
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. %
35 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
43 #include "MagickCore/studio.h"
44 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
45 #define WIN32_LEAN_AND_MEAN
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/quantum.h"
59 #include "MagickCore/string_.h"
60 #include "MagickCore/token.h"
61 #include "MagickCore/splay-tree.h"
62 #include "MagickCore/utility.h"
63 #include "MagickCore/nt-feature.h"
66 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
70 % C r o p I m a g e T o H B i t m a p %
74 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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.
81 % The format of the CropImageToHBITMAP method is:
83 % HBITMAP CropImageToHBITMAP(Image* image,const RectangleInfo *geometry,
84 % ExceptionInfo *exception)
86 % A description of each parameter follows:
90 % o geometry: Define the region of the image to crop with members
91 % x, y, width, and height.
93 % o exception: return any errors or warnings in this structure.
96 MagickExport void *CropImageToHBITMAP(Image *image,
97 const RectangleInfo *geometry,ExceptionInfo *exception)
99 #define CropImageTag "Crop/Image"
116 register const Quantum
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");
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;
159 if ((page.width == 0) || (page.height == 0))
160 ThrowImageException(OptionError,"GeometryDimensionsAreZero");
162 Initialize crop image attributes.
165 bitmap.bmWidth = (LONG) page.width;
166 bitmap.bmHeight = (LONG) page.height;
167 bitmap.bmWidthBytes = bitmap.bmWidth * 4;
169 bitmap.bmBitsPixel = 32;
170 bitmap.bmBits = NULL;
172 bitmap_bitsH=(HANDLE) GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,page.width*
173 page.height*bitmap.bmBitsPixel);
174 if (bitmap_bitsH == 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,RGBColorspace);
185 for (y=0; y < (ssize_t) page.height; y++)
187 p=GetVirtualPixels(image,page.x,page.y+y,page.width,1,exception);
188 if (p == (const Quantum *) NULL)
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));
196 #else /* 16 or 32 bit Quantum */
201 /* Transfer pixels, scaling to Quantum */
202 for( x=(ssize_t) page.width ; x> 0 ; x-- )
204 q->rgbRed = ScaleQuantumToChar(GetPixelRed(image,p));
205 q->rgbGreen = ScaleQuantumToChar(GetPixelGreen(image,p));
206 q->rgbBlue = ScaleQuantumToChar(GetPixelBlue(image,p));
213 proceed=SetImageProgress(image,CropImageTag,y,page.height);
214 if (proceed == MagickFalse)
217 if (y < (ssize_t) page.height)
219 GlobalUnlock((HGLOBAL) bitmap_bitsH);
220 GlobalFree((HGLOBAL) bitmap_bitsH);
221 return((void *) NULL);
223 bitmap.bmBits=bitmap_bits;
224 bitmapH=CreateBitmapIndirect(&bitmap);
225 GlobalUnlock((HGLOBAL) bitmap_bitsH);
226 GlobalFree((HGLOBAL) bitmap_bitsH);
227 return((void *) bitmapH);
231 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
235 % I s M a g i c k C o n f l i c t %
239 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
241 % IsMagickConflict() returns true if the image format conflicts with a logical
244 % The format of the IsMagickConflict method is:
246 % MagickBooleanType IsMagickConflict(const char *magick)
248 % A description of each parameter follows:
250 % o magick: Specifies the image format.
253 MagickExport MagickBooleanType NTIsMagickConflict(const char *magick)
258 assert(magick != (char *) NULL);
259 if (strlen(magick) > 1)
261 status=(GetLogicalDrives() & (1 << ((toupper((int) (*magick)))-'A'))) != 0 ?
262 MagickTrue : MagickFalse;
267 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
271 + N T G e t T y pe L i s t %
275 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
277 % NTLoadTypeLists() loads a Windows TrueType fonts.
279 % The format of the NTLoadTypeLists method is:
281 % MagickBooleanType NTLoadTypeLists(SplayTreeInfo *type_list)
283 % A description of each parameter follows:
285 % o type_list: A linked list of fonts.
288 MagickExport MagickBooleanType NTLoadTypeLists(SplayTreeInfo *type_list,
289 ExceptionInfo *exception)
292 reg_key = (HKEY) INVALID_HANDLE_VALUE;
302 buffer[MaxTextExtent],
303 system_root[MaxTextExtent],
304 font_root[MaxTextExtent];
314 Try to find the right Windows*\CurrentVersion key, the SystemRoot and
317 res = RegOpenKeyExA (HKEY_LOCAL_MACHINE,
318 "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_READ, ®_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);
324 if (res != ERROR_SUCCESS) {
325 res = RegOpenKeyExA (HKEY_LOCAL_MACHINE,
326 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", 0, KEY_READ, ®_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);
333 if (res == ERROR_SUCCESS)
334 res = RegOpenKeyExA (reg_key, "Fonts",0, KEY_READ, ®_key);
335 if (res != ERROR_SUCCESS)
338 (void) CopyMagickString(buffer,system_root,MaxTextExtent);
339 (void) ConcatenateMagickString(buffer,"\\fonts\\arial.ttf",MaxTextExtent);
340 if (IsPathAccessible(buffer) != MagickFalse)
342 (void) CopyMagickString(font_root,system_root,MaxTextExtent);
343 (void) ConcatenateMagickString(font_root,"\\fonts\\",MaxTextExtent);
347 (void) CopyMagickString(font_root,system_root,MaxTextExtent);
348 (void) ConcatenateMagickString(font_root,"\\",MaxTextExtent);
362 value_data[MaxTextExtent],
363 value_name[MaxTextExtent];
367 while (res != ERROR_NO_MORE_ITEMS)
371 token[MaxTextExtent],
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);
380 if (res != ERROR_SUCCESS)
382 if ( (pos = strstr(value_name, " (TrueType)")) == (char*) NULL )
384 *pos='\0'; /* Remove (TrueType) from string */
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));
391 type_info->path=ConstantString("Windows Fonts");
392 type_info->signature=MagickSignature;
395 (void) CopyMagickString(buffer,value_name,MaxTextExtent);
396 for(pos = buffer; *pos != 0 ; pos++)
399 type_info->name=ConstantString(buffer);
402 type_info->description=ConstantString(value_name);
405 type_info->format=ConstantString("truetype");
408 if (strchr(value_data,'\\') != (char *) NULL)
409 (void) CopyMagickString(buffer,value_data,MaxTextExtent);
412 (void) CopyMagickString(buffer,font_root,MaxTextExtent);
413 (void) ConcatenateMagickString(buffer,value_data,MaxTextExtent);
417 type_info->glyphs=ConstantString(buffer);
419 type_info->stretch=NormalStretch;
420 type_info->style=NormalStyle;
421 type_info->weight=400;
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");
430 family_extent=value_name;
432 for (q=value_name; *q != '\0'; )
434 GetMagickToken(q,(const char **) &q,token);
438 if (LocaleCompare(token,"Italic") == 0)
440 type_info->style=ItalicStyle;
443 else if (LocaleCompare(token,"Oblique") == 0)
445 type_info->style=ObliqueStyle;
448 else if (LocaleCompare(token,"Bold") == 0)
450 type_info->weight=700;
453 else if (LocaleCompare(token,"Thin") == 0)
455 type_info->weight=100;
458 else if ( (LocaleCompare(token,"ExtraLight") == 0) ||
459 (LocaleCompare(token,"UltraLight") == 0) )
461 type_info->weight=200;
464 else if (LocaleCompare(token,"Light") == 0)
466 type_info->weight=300;
469 else if ( (LocaleCompare(token,"Normal") == 0) ||
470 (LocaleCompare(token,"Regular") == 0) )
472 type_info->weight=400;
475 else if (LocaleCompare(token,"Medium") == 0)
477 type_info->weight=500;
480 else if ( (LocaleCompare(token,"SemiBold") == 0) ||
481 (LocaleCompare(token,"DemiBold") == 0) )
483 type_info->weight=600;
486 else if ( (LocaleCompare(token,"ExtraBold") == 0) ||
487 (LocaleCompare(token,"UltraBold") == 0) )
489 type_info->weight=800;
492 else if ( (LocaleCompare(token,"Heavy") == 0) ||
493 (LocaleCompare(token,"Black") == 0) )
495 type_info->weight=900;
498 else if (LocaleCompare(token,"Condensed") == 0)
500 type_info->stretch = CondensedStretch;
503 else if (LocaleCompare(token,"Expanded") == 0)
505 type_info->stretch = ExpandedStretch;
508 else if (LocaleCompare(token,"ExtraCondensed") == 0)
510 type_info->stretch = ExtraCondensedStretch;
513 else if (LocaleCompare(token,"ExtraExpanded") == 0)
515 type_info->stretch = ExtraExpandedStretch;
518 else if (LocaleCompare(token,"SemiCondensed") == 0)
520 type_info->stretch = SemiCondensedStretch;
523 else if (LocaleCompare(token,"SemiExpanded") == 0)
525 type_info->stretch = SemiExpandedStretch;
528 else if (LocaleCompare(token,"UltraCondensed") == 0)
530 type_info->stretch = UltraCondensedStretch;
533 else if (LocaleCompare(token,"UltraExpanded") == 0)
535 type_info->stretch = UltraExpandedStretch;
544 (void) CopyMagickString(buffer,value_name,family_extent-value_name+1);
546 type_info->family=ConstantString(buffer);
549 status=AddValueToSplayTree(type_list,ConstantString(type_info->name),
551 if (status == MagickFalse)
552 (void) ThrowMagickException(exception,GetMagickModule(),
553 ResourceLimitError,"MemoryAllocationFailed","`%s'",type_info->name);
556 RegCloseKey ( reg_key );
561 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
565 % I m a g e T o H B i t m a p %
569 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
571 % ImageToHBITMAP() creates a Windows HBITMAP from an image.
573 % The format of the ImageToHBITMAP method is:
575 % HBITMAP ImageToHBITMAP(Image *image)
577 % A description of each parameter follows:
579 % o image: the image to convert.
582 MagickExport void *ImageToHBITMAP(Image *image)
599 register const Quantum
614 (void) ResetMagickMemory(&bitmap,0,sizeof(bitmap));
616 bitmap.bmWidth=(LONG) image->columns;
617 bitmap.bmHeight=(LONG) image->rows;
618 bitmap.bmWidthBytes=4*bitmap.bmWidth;
620 bitmap.bmBitsPixel=32;
622 length=bitmap.bmWidthBytes*bitmap.bmHeight;
623 bitmap_bitsH=(HANDLE) GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,length);
624 if (bitmap_bitsH == NULL)
629 message=GetExceptionMessage(errno);
630 (void) ThrowMagickException(&image->exception,GetMagickModule(),
631 ResourceLimitError,"MemoryAllocationFailed","`%s'",message);
632 message=DestroyString(message);
635 bitmap_bits=(RGBQUAD *) GlobalLock((HGLOBAL) bitmap_bitsH);
637 if (bitmap.bmBits == NULL)
638 bitmap.bmBits=bitmap_bits;
639 (void) TransformImageColorspace(image,RGBColorspace);
640 exception=(&image->exception);
641 for (y=0; y < (ssize_t) image->rows; y++)
643 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
644 if (p == (const Quantum *) NULL)
646 for (x=0; x < (ssize_t) image->columns; x++)
648 q->rgbRed=ScaleQuantumToChar(GetPixelRed(image,p));
649 q->rgbGreen=ScaleQuantumToChar(GetPixelGreen(image,p));
650 q->rgbBlue=ScaleQuantumToChar(GetPixelBlue(image,p));
652 p+=GetPixelComponents(image);
656 bitmap.bmBits=bitmap_bits;
657 bitmapH=CreateBitmapIndirect(&bitmap);
663 message=GetExceptionMessage(errno);
664 (void) ThrowMagickException(&image->exception,GetMagickModule(),
665 ResourceLimitError,"MemoryAllocationFailed","`%s'",message);
666 message=DestroyString(message);
668 GlobalUnlock((HGLOBAL) bitmap_bitsH);
669 GlobalFree((HGLOBAL) bitmap_bitsH);
670 return((void *) bitmapH);