2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14 % Windows NT Feature Methods for MagickCore %
21 % Copyright 1999-2010 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 "magick/studio.h"
44 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
45 #define WIN32_LEAN_AND_MEAN
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"
65 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
69 % C r o p I m a g e T o H B i t m a p %
73 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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.
80 % The format of the CropImageToHBITMAP method is:
82 % HBITMAP CropImageToHBITMAP(Image* image,const RectangleInfo *geometry,
83 % ExceptionInfo *exception)
85 % A description of each parameter follows:
89 % o geometry: Define the region of the image to crop with members
90 % x, y, width, and height.
92 % o exception: return any errors or warnings in this structure.
95 MagickExport void *CropImageToHBITMAP(Image *image,
96 const RectangleInfo *geometry,ExceptionInfo *exception)
98 #define CropImageTag "Crop/Image"
109 register const PixelPacket
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+(long) geometry->width) < 0) ||
138 ((geometry->y+(long) geometry->height) < 0) ||
139 (geometry->x >= (long) image->columns) ||
140 (geometry->y >= (long) image->rows))
141 ThrowImageException(OptionError,"GeometryDoesNotContainImage");
143 if ((page.x+(long) page.width) > (long) image->columns)
144 page.width=image->columns-page.x;
145 if ((page.y+(long) page.height) > (long) image->rows)
146 page.height=image->rows-page.y;
158 if ((page.width == 0) || (page.height == 0))
159 ThrowImageException(OptionError,"GeometryDimensionsAreZero");
161 Initialize crop image attributes.
164 bitmap.bmWidth = page.width;
165 bitmap.bmHeight = page.height;
166 bitmap.bmWidthBytes = bitmap.bmWidth * 4;
168 bitmap.bmBitsPixel = 32;
169 bitmap.bmBits = NULL;
171 bitmap_bitsH=(HANDLE) GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,page.width*
172 page.height*bitmap.bmBitsPixel);
173 if (bitmap_bitsH == 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);
184 for (y=0; y < (long) page.height; y++)
186 p=GetVirtualPixels(image,page.x,page.y+y,page.width,1,exception);
187 if (p == (const PixelPacket *) NULL)
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));
195 #else /* 16 or 32 bit Quantum */
200 /* Transfer pixels, scaling to Quantum */
201 for( x=page.width ; x> 0 ; x-- )
203 q->rgbRed = ScaleQuantumToChar(GetRedPixelComponent(p));
204 q->rgbGreen = ScaleQuantumToChar(GetGreenPixelComponent(p));
205 q->rgbBlue = ScaleQuantumToChar(GetBluePixelComponent(p));
212 proceed=SetImageProgress(image,CropImageTag,y,page.height);
213 if (proceed == MagickFalse)
216 if (y < (long) page.height)
218 GlobalUnlock((HGLOBAL) bitmap_bitsH);
219 GlobalFree((HGLOBAL) bitmap_bitsH);
220 return((void *) NULL);
222 bitmap.bmBits=bitmap_bits;
223 bitmapH=CreateBitmapIndirect(&bitmap);
224 GlobalUnlock((HGLOBAL) bitmap_bitsH);
225 GlobalFree((HGLOBAL) bitmap_bitsH);
226 return((void *) bitmapH);
230 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
234 % I s M a g i c k C o n f l i c t %
238 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
240 % IsMagickConflict() returns true if the image format conflicts with a logical
243 % The format of the IsMagickConflict method is:
245 % MagickBooleanType IsMagickConflict(const char *magick)
247 % A description of each parameter follows:
249 % o magick: Specifies the image format.
252 MagickExport MagickBooleanType NTIsMagickConflict(const char *magick)
257 assert(magick != (char *) NULL);
258 if (strlen(magick) > 1)
260 status=(GetLogicalDrives() & (1 << ((toupper((int) (*magick)))-'A'))) != 0 ?
261 MagickTrue : MagickFalse;
266 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
270 + N T G e t T y pe L i s t %
274 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
276 % NTLoadTypeLists() loads a Windows TrueType fonts.
278 % The format of the NTLoadTypeLists method is:
280 % MagickBooleanType NTLoadTypeLists(SplayTreeInfo *type_list)
282 % A description of each parameter follows:
284 % o type_list: A linked list of fonts.
287 MagickExport MagickBooleanType NTLoadTypeLists(SplayTreeInfo *type_list,
288 ExceptionInfo *exception)
291 reg_key = (HKEY) INVALID_HANDLE_VALUE;
301 buffer[MaxTextExtent],
302 system_root[MaxTextExtent],
303 font_root[MaxTextExtent];
313 Try to find the right Windows*\CurrentVersion key, the SystemRoot and
316 res = RegOpenKeyExA (HKEY_LOCAL_MACHINE,
317 "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_READ, ®_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);
323 if (res != ERROR_SUCCESS) {
324 res = RegOpenKeyExA (HKEY_LOCAL_MACHINE,
325 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", 0, KEY_READ, ®_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);
332 if (res == ERROR_SUCCESS)
333 res = RegOpenKeyExA (reg_key, "Fonts",0, KEY_READ, ®_key);
334 if (res != ERROR_SUCCESS)
337 (void) CopyMagickString(buffer,system_root,MaxTextExtent);
338 (void) ConcatenateMagickString(buffer,"\\fonts\\arial.ttf",MaxTextExtent);
339 if (IsPathAccessible(buffer) != MagickFalse)
341 (void) CopyMagickString(font_root,system_root,MaxTextExtent);
342 (void) ConcatenateMagickString(font_root,"\\fonts\\",MaxTextExtent);
346 (void) CopyMagickString(font_root,system_root,MaxTextExtent);
347 (void) ConcatenateMagickString(font_root,"\\",MaxTextExtent);
361 value_data[MaxTextExtent],
362 value_name[MaxTextExtent];
366 while (res != ERROR_NO_MORE_ITEMS)
370 token[MaxTextExtent],
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);
379 if (res != ERROR_SUCCESS)
381 if ( (pos = strstr(value_name, " (TrueType)")) == (char*) NULL )
383 *pos='\0'; /* Remove (TrueType) from string */
385 type_info=(TypeInfo *) AcquireAlignedMemory(1,sizeof(*type_info));
386 if (type_info == (TypeInfo *) NULL)
387 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
388 (void) ResetMagickMemory(type_info,0,sizeof(TypeInfo));
390 type_info->path=ConstantString("Windows Fonts");
391 type_info->signature=MagickSignature;
394 (void) CopyMagickString(buffer,value_name,MaxTextExtent);
395 for(pos = buffer; *pos != 0 ; pos++)
398 type_info->name=ConstantString(buffer);
401 type_info->description=ConstantString(value_name);
404 type_info->format=ConstantString("truetype");
407 if (strchr(value_data,'\\') != (char *) NULL)
408 (void) CopyMagickString(buffer,value_data,MaxTextExtent);
411 (void) CopyMagickString(buffer,font_root,MaxTextExtent);
412 (void) ConcatenateMagickString(buffer,value_data,MaxTextExtent);
416 type_info->glyphs=ConstantString(buffer);
418 type_info->stretch=NormalStretch;
419 type_info->style=NormalStyle;
420 type_info->weight=400;
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");
429 family_extent=value_name;
431 for (q=value_name; *q != '\0'; )
433 GetMagickToken(q,(const char **) &q,token);
437 if (LocaleCompare(token,"Italic") == 0)
439 type_info->style=ItalicStyle;
442 else if (LocaleCompare(token,"Oblique") == 0)
444 type_info->style=ObliqueStyle;
447 else if (LocaleCompare(token,"Bold") == 0)
449 type_info->weight=700;
452 else if (LocaleCompare(token,"Thin") == 0)
454 type_info->weight=100;
457 else if ( (LocaleCompare(token,"ExtraLight") == 0) ||
458 (LocaleCompare(token,"UltraLight") == 0) )
460 type_info->weight=200;
463 else if (LocaleCompare(token,"Light") == 0)
465 type_info->weight=300;
468 else if ( (LocaleCompare(token,"Normal") == 0) ||
469 (LocaleCompare(token,"Regular") == 0) )
471 type_info->weight=400;
474 else if (LocaleCompare(token,"Medium") == 0)
476 type_info->weight=500;
479 else if ( (LocaleCompare(token,"SemiBold") == 0) ||
480 (LocaleCompare(token,"DemiBold") == 0) )
482 type_info->weight=600;
485 else if ( (LocaleCompare(token,"ExtraBold") == 0) ||
486 (LocaleCompare(token,"UltraBold") == 0) )
488 type_info->weight=800;
491 else if ( (LocaleCompare(token,"Heavy") == 0) ||
492 (LocaleCompare(token,"Black") == 0) )
494 type_info->weight=900;
497 else if (LocaleCompare(token,"Condensed") == 0)
499 type_info->stretch = CondensedStretch;
502 else if (LocaleCompare(token,"Expanded") == 0)
504 type_info->stretch = ExpandedStretch;
507 else if (LocaleCompare(token,"ExtraCondensed") == 0)
509 type_info->stretch = ExtraCondensedStretch;
512 else if (LocaleCompare(token,"ExtraExpanded") == 0)
514 type_info->stretch = ExtraExpandedStretch;
517 else if (LocaleCompare(token,"SemiCondensed") == 0)
519 type_info->stretch = SemiCondensedStretch;
522 else if (LocaleCompare(token,"SemiExpanded") == 0)
524 type_info->stretch = SemiExpandedStretch;
527 else if (LocaleCompare(token,"UltraCondensed") == 0)
529 type_info->stretch = UltraCondensedStretch;
532 else if (LocaleCompare(token,"UltraExpanded") == 0)
534 type_info->stretch = UltraExpandedStretch;
543 (void) CopyMagickString(buffer,value_name,family_extent-value_name+1);
545 type_info->family=ConstantString(buffer);
548 status=AddValueToSplayTree(type_list,ConstantString(type_info->name),
550 if (status == MagickFalse)
551 (void) ThrowMagickException(exception,GetMagickModule(),
552 ResourceLimitError,"MemoryAllocationFailed","`%s'",type_info->name);
555 RegCloseKey ( reg_key );
560 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
564 % I m a g e T o H B i t m a p %
568 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
570 % ImageToHBITMAP() creates a Windows HBITMAP from an image.
572 % The format of the ImageToHBITMAP method is:
574 % HBITMAP ImageToHBITMAP(Image *image)
576 % A description of each parameter follows:
578 % o image: the image to convert.
581 MagickExport void *ImageToHBITMAP(Image *image)
601 register const PixelPacket
613 (void) ResetMagickMemory(&bitmap,0,sizeof(bitmap));
615 bitmap.bmWidth=image->columns;
616 bitmap.bmHeight=image->rows;
617 bitmap.bmWidthBytes=4*bitmap.bmWidth;
619 bitmap.bmBitsPixel=32;
621 length=bitmap.bmWidthBytes*bitmap.bmHeight;
622 bitmap_bitsH=(HANDLE) GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,length);
623 if (bitmap_bitsH == NULL)
628 message=GetExceptionMessage(errno);
629 (void) ThrowMagickException(&image->exception,GetMagickModule(),
630 ResourceLimitError,"MemoryAllocationFailed","`%s'",message);
631 message=DestroyString(message);
634 bitmap_bits=(RGBQUAD *) GlobalLock((HGLOBAL) bitmap_bitsH);
636 if (bitmap.bmBits == NULL)
637 bitmap.bmBits=bitmap_bits;
638 (void) TransformImageColorspace(image,RGBColorspace);
639 exception=(&image->exception);
640 for (y=0; y < (long) image->rows; y++)
642 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
643 if (p == (const PixelPacket *) NULL)
645 for (x=0; x < (long) image->columns; x++)
647 q->rgbRed=ScaleQuantumToChar(GetRedPixelComponent(p));
648 q->rgbGreen=ScaleQuantumToChar(GetGreenPixelComponent(p));
649 q->rgbBlue=ScaleQuantumToChar(GetBluePixelComponent(p));
655 bitmap.bmBits=bitmap_bits;
656 bitmapH=CreateBitmapIndirect(&bitmap);
662 message=GetExceptionMessage(errno);
663 (void) ThrowMagickException(&image->exception,GetMagickModule(),
664 ResourceLimitError,"MemoryAllocationFailed","`%s'",message);
665 message=DestroyString(message);
667 GlobalUnlock((HGLOBAL) bitmap_bitsH);
668 GlobalFree((HGLOBAL) bitmap_bitsH);
669 return((void *) bitmapH);