00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include "magick/studio.h"
00043 #include "magick/artifact.h"
00044 #include "magick/blob.h"
00045 #include "magick/cache.h"
00046 #include "magick/client.h"
00047 #include "magick/color.h"
00048 #include "magick/colorspace.h"
00049 #include "magick/composite.h"
00050 #include "magick/constitute.h"
00051 #include "magick/decorate.h"
00052 #include "magick/delegate.h"
00053 #include "magick/display.h"
00054 #include "magick/display-private.h"
00055 #include "magick/draw.h"
00056 #include "magick/effect.h"
00057 #include "magick/enhance.h"
00058 #include "magick/exception.h"
00059 #include "magick/exception-private.h"
00060 #include "magick/fx.h"
00061 #include "magick/geometry.h"
00062 #include "magick/image.h"
00063 #include "magick/image-private.h"
00064 #include "magick/list.h"
00065 #include "magick/log.h"
00066 #include "magick/magick.h"
00067 #include "magick/memory_.h"
00068 #include "magick/monitor.h"
00069 #include "magick/monitor-private.h"
00070 #include "magick/montage.h"
00071 #include "magick/option.h"
00072 #include "magick/paint.h"
00073 #include "magick/pixel.h"
00074 #include "magick/pixel-private.h"
00075 #include "magick/PreRvIcccm.h"
00076 #include "magick/property.h"
00077 #include "magick/quantum.h"
00078 #include "magick/resize.h"
00079 #include "magick/resource_.h"
00080 #include "magick/shear.h"
00081 #include "magick/segment.h"
00082 #include "magick/string_.h"
00083 #include "magick/transform.h"
00084 #include "magick/threshold.h"
00085 #include "magick/utility.h"
00086 #include "magick/version.h"
00087 #include "magick/widget.h"
00088 #include "magick/xwindow-private.h"
00089
00090 #if defined(MAGICKCORE_X11_DELEGATE)
00091
00092
00093
00094 #define MaxColors MagickMin(windows->visual_info->colormap_size,256L)
00095
00096
00097
00098
00099 static const unsigned char
00100 HighlightBitmap[8] =
00101 {
00102 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55
00103 },
00104 ShadowBitmap[8] =
00105 {
00106 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
00107 };
00108
00109 static const char
00110 *PageSizes[] =
00111 {
00112 "Letter",
00113 "Tabloid",
00114 "Ledger",
00115 "Legal",
00116 "Statement",
00117 "Executive",
00118 "A3",
00119 "A4",
00120 "A5",
00121 "B4",
00122 "B5",
00123 "Folio",
00124 "Quarto",
00125 "10x14",
00126 (char *) NULL
00127 };
00128
00129
00130
00131
00132 static const char
00133 *ImageAnnotateHelp[] =
00134 {
00135 "In annotate mode, the Command widget has these options:",
00136 "",
00137 " Font Name",
00138 " fixed",
00139 " variable",
00140 " 5x8",
00141 " 6x10",
00142 " 7x13bold",
00143 " 8x13bold",
00144 " 9x15bold",
00145 " 10x20",
00146 " 12x24",
00147 " Browser...",
00148 " Font Color",
00149 " black",
00150 " blue",
00151 " cyan",
00152 " green",
00153 " gray",
00154 " red",
00155 " magenta",
00156 " yellow",
00157 " white",
00158 " transparent",
00159 " Browser...",
00160 " Font Color",
00161 " black",
00162 " blue",
00163 " cyan",
00164 " green",
00165 " gray",
00166 " red",
00167 " magenta",
00168 " yellow",
00169 " white",
00170 " transparent",
00171 " Browser...",
00172 " Rotate Text",
00173 " -90",
00174 " -45",
00175 " -30",
00176 " 0",
00177 " 30",
00178 " 45",
00179 " 90",
00180 " 180",
00181 " Dialog...",
00182 " Help",
00183 " Dismiss",
00184 "",
00185 "Choose a font name from the Font Name sub-menu. Additional",
00186 "font names can be specified with the font browser. You can",
00187 "change the menu names by setting the X resources font1",
00188 "through font9.",
00189 "",
00190 "Choose a font color from the Font Color sub-menu.",
00191 "Additional font colors can be specified with the color",
00192 "browser. You can change the menu colors by setting the X",
00193 "resources pen1 through pen9.",
00194 "",
00195 "If you select the color browser and press Grab, you can",
00196 "choose the font color by moving the pointer to the desired",
00197 "color on the screen and press any button.",
00198 "",
00199 "If you choose to rotate the text, choose Rotate Text from the",
00200 "menu and select an angle. Typically you will only want to",
00201 "rotate one line of text at a time. Depending on the angle you",
00202 "choose, subsequent lines may end up overwriting each other.",
00203 "",
00204 "Choosing a font and its color is optional. The default font",
00205 "is fixed and the default color is black. However, you must",
00206 "choose a location to begin entering text and press button 1.",
00207 "An underscore character will appear at the location of the",
00208 "pointer. The cursor changes to a pencil to indicate you are",
00209 "in text mode. To exit immediately, press Dismiss.",
00210 "",
00211 "In text mode, any key presses will display the character at",
00212 "the location of the underscore and advance the underscore",
00213 "cursor. Enter your text and once completed press Apply to",
00214 "finish your image annotation. To correct errors press BACK",
00215 "SPACE. To delete an entire line of text, press DELETE. Any",
00216 "text that exceeds the boundaries of the image window is",
00217 "automatically continued onto the next line.",
00218 "",
00219 "The actual color you request for the font is saved in the",
00220 "image. However, the color that appears in your image window",
00221 "may be different. For example, on a monochrome screen the",
00222 "text will appear black or white even if you choose the color",
00223 "red as the font color. However, the image saved to a file",
00224 "with -write is written with red lettering. To assure the",
00225 "correct color text in the final image, any PseudoClass image",
00226 "is promoted to DirectClass (see miff(5)). To force a",
00227 "PseudoClass image to remain PseudoClass, use -colors.",
00228 (char *) NULL,
00229 },
00230 *ImageChopHelp[] =
00231 {
00232 "In chop mode, the Command widget has these options:",
00233 "",
00234 " Direction",
00235 " horizontal",
00236 " vertical",
00237 " Help",
00238 " Dismiss",
00239 "",
00240 "If the you choose the horizontal direction (this the",
00241 "default), the area of the image between the two horizontal",
00242 "endpoints of the chop line is removed. Otherwise, the area",
00243 "of the image between the two vertical endpoints of the chop",
00244 "line is removed.",
00245 "",
00246 "Select a location within the image window to begin your chop,",
00247 "press and hold any button. Next, move the pointer to",
00248 "another location in the image. As you move a line will",
00249 "connect the initial location and the pointer. When you",
00250 "release the button, the area within the image to chop is",
00251 "determined by which direction you choose from the Command",
00252 "widget.",
00253 "",
00254 "To cancel the image chopping, move the pointer back to the",
00255 "starting point of the line and release the button.",
00256 (char *) NULL,
00257 },
00258 *ImageColorEditHelp[] =
00259 {
00260 "In color edit mode, the Command widget has these options:",
00261 "",
00262 " Method",
00263 " point",
00264 " replace",
00265 " floodfill",
00266 " filltoborder",
00267 " reset",
00268 " Pixel Color",
00269 " black",
00270 " blue",
00271 " cyan",
00272 " green",
00273 " gray",
00274 " red",
00275 " magenta",
00276 " yellow",
00277 " white",
00278 " Browser...",
00279 " Border Color",
00280 " black",
00281 " blue",
00282 " cyan",
00283 " green",
00284 " gray",
00285 " red",
00286 " magenta",
00287 " yellow",
00288 " white",
00289 " Browser...",
00290 " Fuzz",
00291 " 0%",
00292 " 2%",
00293 " 5%",
00294 " 10%",
00295 " 15%",
00296 " Dialog...",
00297 " Undo",
00298 " Help",
00299 " Dismiss",
00300 "",
00301 "Choose a color editing method from the Method sub-menu",
00302 "of the Command widget. The point method recolors any pixel",
00303 "selected with the pointer until the button is released. The",
00304 "replace method recolors any pixel that matches the color of",
00305 "the pixel you select with a button press. Floodfill recolors",
00306 "any pixel that matches the color of the pixel you select with",
00307 "a button press and is a neighbor. Whereas filltoborder recolors",
00308 "any neighbor pixel that is not the border color. Finally reset",
00309 "changes the entire image to the designated color.",
00310 "",
00311 "Next, choose a pixel color from the Pixel Color sub-menu.",
00312 "Additional pixel colors can be specified with the color",
00313 "browser. You can change the menu colors by setting the X",
00314 "resources pen1 through pen9.",
00315 "",
00316 "Now press button 1 to select a pixel within the image window",
00317 "to change its color. Additional pixels may be recolored as",
00318 "prescribed by the method you choose.",
00319 "",
00320 "If the Magnify widget is mapped, it can be helpful in positioning",
00321 "your pointer within the image (refer to button 2).",
00322 "",
00323 "The actual color you request for the pixels is saved in the",
00324 "image. However, the color that appears in your image window",
00325 "may be different. For example, on a monochrome screen the",
00326 "pixel will appear black or white even if you choose the",
00327 "color red as the pixel color. However, the image saved to a",
00328 "file with -write is written with red pixels. To assure the",
00329 "correct color text in the final image, any PseudoClass image",
00330 "is promoted to DirectClass (see miff(5)). To force a",
00331 "PseudoClass image to remain PseudoClass, use -colors.",
00332 (char *) NULL,
00333 },
00334 *ImageCompositeHelp[] =
00335 {
00336 "First a widget window is displayed requesting you to enter an",
00337 "image name. Press Composite, Grab or type a file name.",
00338 "Press Cancel if you choose not to create a composite image.",
00339 "When you choose Grab, move the pointer to the desired window",
00340 "and press any button.",
00341 "",
00342 "If the Composite image does not have any matte information,",
00343 "you are informed and the file browser is displayed again.",
00344 "Enter the name of a mask image. The image is typically",
00345 "grayscale and the same size as the composite image. If the",
00346 "image is not grayscale, it is converted to grayscale and the",
00347 "resulting intensities are used as matte information.",
00348 "",
00349 "A small window appears showing the location of the cursor in",
00350 "the image window. You are now in composite mode. To exit",
00351 "immediately, press Dismiss. In composite mode, the Command",
00352 "widget has these options:",
00353 "",
00354 " Operators",
00355 " Over",
00356 " In",
00357 " Out",
00358 " Atop",
00359 " Xor",
00360 " Plus",
00361 " Minus",
00362 " Add",
00363 " Subtract",
00364 " Difference",
00365 " Multiply",
00366 " Bumpmap",
00367 " Copy",
00368 " CopyRed",
00369 " CopyGreen",
00370 " CopyBlue",
00371 " CopyOpacity",
00372 " Clear",
00373 " Dissolve",
00374 " Displace",
00375 " Help",
00376 " Dismiss",
00377 "",
00378 "Choose a composite operation from the Operators sub-menu of",
00379 "the Command widget. How each operator behaves is described",
00380 "below. Image window is the image currently displayed on",
00381 "your X server and image is the image obtained with the File",
00382 "Browser widget.",
00383 "",
00384 "Over The result is the union of the two image shapes,",
00385 " with image obscuring image window in the region of",
00386 " overlap.",
00387 "",
00388 "In The result is simply image cut by the shape of",
00389 " image window. None of the image data of image",
00390 " window is in the result.",
00391 "",
00392 "Out The resulting image is image with the shape of",
00393 " image window cut out.",
00394 "",
00395 "Atop The result is the same shape as image image window,",
00396 " with image obscuring image window where the image",
00397 " shapes overlap. Note this differs from over",
00398 " because the portion of image outside image window's",
00399 " shape does not appear in the result.",
00400 "",
00401 "Xor The result is the image data from both image and",
00402 " image window that is outside the overlap region.",
00403 " The overlap region is blank.",
00404 "",
00405 "Plus The result is just the sum of the image data.",
00406 " Output values are cropped to QuantumRange (no overflow).",
00407 "",
00408 "Minus The result of image - image window, with underflow",
00409 " cropped to zero.",
00410 "",
00411 "Add The result of image + image window, with overflow",
00412 " wrapping around (mod 256).",
00413 "",
00414 "Subtract The result of image - image window, with underflow",
00415 " wrapping around (mod 256). The add and subtract",
00416 " operators can be used to perform reversible",
00417 " transformations.",
00418 "",
00419 "Difference",
00420 " The result of abs(image - image window). This",
00421 " useful for comparing two very similar images.",
00422 "",
00423 "Multiply",
00424 " The result of image * image window. This",
00425 " useful for the creation of drop-shadows.",
00426 "",
00427 "Bumpmap The result of surface normals from image * image",
00428 " window.",
00429 "",
00430 "Copy The resulting image is image window replaced with",
00431 " image. Here the matte information is ignored.",
00432 "",
00433 "CopyRed The red layer of the image window is replace with",
00434 " the red layer of the image. The other layers are",
00435 " untouched.",
00436 "",
00437 "CopyGreen",
00438 " The green layer of the image window is replace with",
00439 " the green layer of the image. The other layers are",
00440 " untouched.",
00441 "",
00442 "CopyBlue The blue layer of the image window is replace with",
00443 " the blue layer of the image. The other layers are",
00444 " untouched.",
00445 "",
00446 "CopyOpacity",
00447 " The matte layer of the image window is replace with",
00448 " the matte layer of the image. The other layers are",
00449 " untouched.",
00450 "",
00451 "The image compositor requires a matte, or alpha channel in",
00452 "the image for some operations. This extra channel usually",
00453 "defines a mask which represents a sort of a cookie-cutter",
00454 "for the image. This the case when matte is opaque (full",
00455 "coverage) for pixels inside the shape, zero outside, and",
00456 "between 0 and QuantumRange on the boundary. If image does not",
00457 "have a matte channel, it is initialized with 0 for any pixel",
00458 "matching in color to pixel location (0,0), otherwise QuantumRange.",
00459 "",
00460 "If you choose Dissolve, the composite operator becomes Over. The",
00461 "image matte channel percent transparency is initialized to factor.",
00462 "The image window is initialized to (100-factor). Where factor is the",
00463 "value you specify in the Dialog widget.",
00464 "",
00465 "Displace shifts the image pixels as defined by a displacement",
00466 "map. With this option, image is used as a displacement map.",
00467 "Black, within the displacement map, is a maximum positive",
00468 "displacement. White is a maximum negative displacement and",
00469 "middle gray is neutral. The displacement is scaled to determine",
00470 "the pixel shift. By default, the displacement applies in both the",
00471 "horizontal and vertical directions. However, if you specify a mask,",
00472 "image is the horizontal X displacement and mask the vertical Y",
00473 "displacement.",
00474 "",
00475 "Note that matte information for image window is not retained",
00476 "for colormapped X server visuals (e.g. StaticColor,",
00477 "StaticColor, GrayScale, PseudoColor). Correct compositing",
00478 "behavior may require a TrueColor or DirectColor visual or a",
00479 "Standard Colormap.",
00480 "",
00481 "Choosing a composite operator is optional. The default",
00482 "operator is replace. However, you must choose a location to",
00483 "composite your image and press button 1. Press and hold the",
00484 "button before releasing and an outline of the image will",
00485 "appear to help you identify your location.",
00486 "",
00487 "The actual colors of the composite image is saved. However,",
00488 "the color that appears in image window may be different.",
00489 "For example, on a monochrome screen image window will appear",
00490 "black or white even though your composited image may have",
00491 "many colors. If the image is saved to a file it is written",
00492 "with the correct colors. To assure the correct colors are",
00493 "saved in the final image, any PseudoClass image is promoted",
00494 "to DirectClass (see miff(5)). To force a PseudoClass image",
00495 "to remain PseudoClass, use -colors.",
00496 (char *) NULL,
00497 },
00498 *ImageCutHelp[] =
00499 {
00500 "In cut mode, the Command widget has these options:",
00501 "",
00502 " Help",
00503 " Dismiss",
00504 "",
00505 "To define a cut region, press button 1 and drag. The",
00506 "cut region is defined by a highlighted rectangle that",
00507 "expands or contracts as it follows the pointer. Once you",
00508 "are satisfied with the cut region, release the button.",
00509 "You are now in rectify mode. In rectify mode, the Command",
00510 "widget has these options:",
00511 "",
00512 " Cut",
00513 " Help",
00514 " Dismiss",
00515 "",
00516 "You can make adjustments by moving the pointer to one of the",
00517 "cut rectangle corners, pressing a button, and dragging.",
00518 "Finally, press Cut to commit your copy region. To",
00519 "exit without cutting the image, press Dismiss.",
00520 (char *) NULL,
00521 },
00522 *ImageCopyHelp[] =
00523 {
00524 "In copy mode, the Command widget has these options:",
00525 "",
00526 " Help",
00527 " Dismiss",
00528 "",
00529 "To define a copy region, press button 1 and drag. The",
00530 "copy region is defined by a highlighted rectangle that",
00531 "expands or contracts as it follows the pointer. Once you",
00532 "are satisfied with the copy region, release the button.",
00533 "You are now in rectify mode. In rectify mode, the Command",
00534 "widget has these options:",
00535 "",
00536 " Copy",
00537 " Help",
00538 " Dismiss",
00539 "",
00540 "You can make adjustments by moving the pointer to one of the",
00541 "copy rectangle corners, pressing a button, and dragging.",
00542 "Finally, press Copy to commit your copy region. To",
00543 "exit without copying the image, press Dismiss.",
00544 (char *) NULL,
00545 },
00546 *ImageCropHelp[] =
00547 {
00548 "In crop mode, the Command widget has these options:",
00549 "",
00550 " Help",
00551 " Dismiss",
00552 "",
00553 "To define a cropping region, press button 1 and drag. The",
00554 "cropping region is defined by a highlighted rectangle that",
00555 "expands or contracts as it follows the pointer. Once you",
00556 "are satisfied with the cropping region, release the button.",
00557 "You are now in rectify mode. In rectify mode, the Command",
00558 "widget has these options:",
00559 "",
00560 " Crop",
00561 " Help",
00562 " Dismiss",
00563 "",
00564 "You can make adjustments by moving the pointer to one of the",
00565 "cropping rectangle corners, pressing a button, and dragging.",
00566 "Finally, press Crop to commit your cropping region. To",
00567 "exit without cropping the image, press Dismiss.",
00568 (char *) NULL,
00569 },
00570 *ImageDrawHelp[] =
00571 {
00572 "The cursor changes to a crosshair to indicate you are in",
00573 "draw mode. To exit immediately, press Dismiss. In draw mode,",
00574 "the Command widget has these options:",
00575 "",
00576 " Element",
00577 " point",
00578 " line",
00579 " rectangle",
00580 " fill rectangle",
00581 " circle",
00582 " fill circle",
00583 " ellipse",
00584 " fill ellipse",
00585 " polygon",
00586 " fill polygon",
00587 " Color",
00588 " black",
00589 " blue",
00590 " cyan",
00591 " green",
00592 " gray",
00593 " red",
00594 " magenta",
00595 " yellow",
00596 " white",
00597 " transparent",
00598 " Browser...",
00599 " Stipple",
00600 " Brick",
00601 " Diagonal",
00602 " Scales",
00603 " Vertical",
00604 " Wavy",
00605 " Translucent",
00606 " Opaque",
00607 " Open...",
00608 " Width",
00609 " 1",
00610 " 2",
00611 " 4",
00612 " 8",
00613 " 16",
00614 " Dialog...",
00615 " Undo",
00616 " Help",
00617 " Dismiss",
00618 "",
00619 "Choose a drawing primitive from the Element sub-menu.",
00620 "",
00621 "Choose a color from the Color sub-menu. Additional",
00622 "colors can be specified with the color browser.",
00623 "",
00624 "If you choose the color browser and press Grab, you can",
00625 "select the color by moving the pointer to the desired",
00626 "color on the screen and press any button. The transparent",
00627 "color updates the image matte channel and is useful for",
00628 "image compositing.",
00629 "",
00630 "Choose a stipple, if appropriate, from the Stipple sub-menu.",
00631 "Additional stipples can be specified with the file browser.",
00632 "Stipples obtained from the file browser must be on disk in the",
00633 "X11 bitmap format.",
00634 "",
00635 "Choose a width, if appropriate, from the Width sub-menu. To",
00636 "choose a specific width select the Dialog widget.",
00637 "",
00638 "Choose a point in the Image window and press button 1 and",
00639 "hold. Next, move the pointer to another location in the",
00640 "image. As you move, a line connects the initial location and",
00641 "the pointer. When you release the button, the image is",
00642 "updated with the primitive you just drew. For polygons, the",
00643 "image is updated when you press and release the button without",
00644 "moving the pointer.",
00645 "",
00646 "To cancel image drawing, move the pointer back to the",
00647 "starting point of the line and release the button.",
00648 (char *) NULL,
00649 },
00650 *DisplayHelp[] =
00651 {
00652 "BUTTONS",
00653 " The effects of each button press is described below. Three",
00654 " buttons are required. If you have a two button mouse,",
00655 " button 1 and 3 are returned. Press ALT and button 3 to",
00656 " simulate button 2.",
00657 "",
00658 " 1 Press this button to map or unmap the Command widget.",
00659 "",
00660 " 2 Press and drag to define a region of the image to",
00661 " magnify.",
00662 "",
00663 " 3 Press and drag to choose from a select set of commands.",
00664 " This button behaves differently if the image being",
00665 " displayed is a visual image directory. Here, choose a",
00666 " particular tile of the directory and press this button and",
00667 " drag to select a command from a pop-up menu. Choose from",
00668 " these menu items:",
00669 "",
00670 " Open",
00671 " Next",
00672 " Former",
00673 " Delete",
00674 " Update",
00675 "",
00676 " If you choose Open, the image represented by the tile is",
00677 " displayed. To return to the visual image directory, choose",
00678 " Next from the Command widget. Next and Former moves to the",
00679 " next or former image respectively. Choose Delete to delete",
00680 " a particular image tile. Finally, choose Update to",
00681 " synchronize all the image tiles with their respective",
00682 " images.",
00683 "",
00684 "COMMAND WIDGET",
00685 " The Command widget lists a number of sub-menus and commands.",
00686 " They are",
00687 "",
00688 " File",
00689 " Open...",
00690 " Next",
00691 " Former",
00692 " Select...",
00693 " Save...",
00694 " Print...",
00695 " Delete...",
00696 " New...",
00697 " Visual Directory...",
00698 " Quit",
00699 " Edit",
00700 " Undo",
00701 " Redo",
00702 " Cut",
00703 " Copy",
00704 " Paste",
00705 " View",
00706 " Half Size",
00707 " Original Size",
00708 " Double Size",
00709 " Resize...",
00710 " Apply",
00711 " Refresh",
00712 " Restore",
00713 " Transform",
00714 " Crop",
00715 " Chop",
00716 " Flop",
00717 " Flip",
00718 " Rotate Right",
00719 " Rotate Left",
00720 " Rotate...",
00721 " Shear...",
00722 " Roll...",
00723 " Trim Edges",
00724 " Enhance",
00725 " Brightness...",
00726 " Saturation...",
00727 " Hue...",
00728 " Gamma...",
00729 " Sharpen...",
00730 " Dull",
00731 " Contrast Stretch...",
00732 " Sigmoidal Contrast...",
00733 " Normalize",
00734 " Equalize",
00735 " Negate",
00736 " Grayscale",
00737 " Map...",
00738 " Quantize...",
00739 " Effects",
00740 " Despeckle",
00741 " Emboss",
00742 " Reduce Noise",
00743 " Add Noise",
00744 " Sharpen...",
00745 " Blur...",
00746 " Threshold...",
00747 " Edge Detect...",
00748 " Spread...",
00749 " Shade...",
00750 " Painting...",
00751 " Segment...",
00752 " F/X",
00753 " Solarize...",
00754 " Sepia Tone...",
00755 " Swirl...",
00756 " Implode...",
00757 " Vignette...",
00758 " Wave...",
00759 " Oil Painting...",
00760 " Charcoal Drawing...",
00761 " Image Edit",
00762 " Annotate...",
00763 " Draw...",
00764 " Color...",
00765 " Matte...",
00766 " Composite...",
00767 " Add Border...",
00768 " Add Frame...",
00769 " Comment...",
00770 " Launch...",
00771 " Region of Interest...",
00772 " Miscellany",
00773 " Image Info",
00774 " Zoom Image",
00775 " Show Preview...",
00776 " Show Histogram",
00777 " Show Matte",
00778 " Background...",
00779 " Slide Show",
00780 " Preferences...",
00781 " Help",
00782 " Overview",
00783 " Browse Documentation",
00784 " About Display",
00785 "",
00786 " Menu items with a indented triangle have a sub-menu. They",
00787 " are represented above as the indented items. To access a",
00788 " sub-menu item, move the pointer to the appropriate menu and",
00789 " press a button and drag. When you find the desired sub-menu",
00790 " item, release the button and the command is executed. Move",
00791 " the pointer away from the sub-menu if you decide not to",
00792 " execute a particular command.",
00793 "",
00794 "KEYBOARD ACCELERATORS",
00795 " Accelerators are one or two key presses that effect a",
00796 " particular command. The keyboard accelerators that",
00797 " display(1) understands is:",
00798 "",
00799 " Ctl+O Press to open an image from a file.",
00800 "",
00801 " space Press to display the next image.",
00802 "",
00803 " If the image is a multi-paged document such as a Postscript",
00804 " document, you can skip ahead several pages by preceeding",
00805 " this command with a number. For example to display the",
00806 " third page beyond the current page, press 3<space>.",
00807 "",
00808 " backspace Press to display the former image.",
00809 "",
00810 " If the image is a multi-paged document such as a Postscript",
00811 " document, you can skip behind several pages by preceeding",
00812 " this command with a number. For example to display the",
00813 " third page preceeding the current page, press 3<backspace>.",
00814 "",
00815 " Ctl+S Press to write the image to a file.",
00816 "",
00817 " Ctl+P Press to print the image to a Postscript printer.",
00818 "",
00819 " Ctl+D Press to delete an image file.",
00820 "",
00821 " Ctl+N Press to create a blank canvas.",
00822 "",
00823 " Ctl+Q Press to discard all images and exit program.",
00824 "",
00825 " Ctl+Z Press to undo last image transformation.",
00826 "",
00827 " Ctl+R Press to redo last image transformation.",
00828 "",
00829 " Ctl+X Press to cut a region of the image.",
00830 "",
00831 " Ctl+C Press to copy a region of the image.",
00832 "",
00833 " Ctl+V Press to paste a region to the image.",
00834 "",
00835 " < Press to half the image size.",
00836 "",
00837 " - Press to return to the original image size.",
00838 "",
00839 " > Press to double the image size.",
00840 "",
00841 " % Press to resize the image to a width and height you",
00842 " specify.",
00843 "",
00844 "Cmd-A Press to make any image transformations permanent."
00845 "",
00846 " By default, any image size transformations are applied",
00847 " to the original image to create the image displayed on",
00848 " the X server. However, the transformations are not",
00849 " permanent (i.e. the original image does not change",
00850 " size only the X image does). For example, if you",
00851 " press > the X image will appear to double in size,",
00852 " but the original image will in fact remain the same size.",
00853 " To force the original image to double in size, press >",
00854 " followed by Cmd-A.",
00855 "",
00856 " @ Press to refresh the image window.",
00857 "",
00858 " C Press to cut out a rectangular region of the image.",
00859 "",
00860 " [ Press to chop the image.",
00861 "",
00862 " H Press to flop image in the horizontal direction.",
00863 "",
00864 " V Press to flip image in the vertical direction.",
00865 "",
00866 " / Press to rotate the image 90 degrees clockwise.",
00867 "",
00868 " \\ Press to rotate the image 90 degrees counter-clockwise.",
00869 "",
00870 " * Press to rotate the image the number of degrees you",
00871 " specify.",
00872 "",
00873 " S Press to shear the image the number of degrees you",
00874 " specify.",
00875 "",
00876 " R Press to roll the image.",
00877 "",
00878 " T Press to trim the image edges.",
00879 "",
00880 " Shft-H Press to vary the image hue.",
00881 "",
00882 " Shft-S Press to vary the color saturation.",
00883 "",
00884 " Shft-L Press to vary the color brightness.",
00885 "",
00886 " Shft-G Press to gamma correct the image.",
00887 "",
00888 " Shft-C Press to sharpen the image contrast.",
00889 "",
00890 " Shft-Z Press to dull the image contrast.",
00891 "",
00892 " = Press to perform histogram equalization on the image.",
00893 "",
00894 " Shft-N Press to perform histogram normalization on the image.",
00895 "",
00896 " Shft-~ Press to negate the colors of the image.",
00897 "",
00898 " . Press to convert the image colors to gray.",
00899 "",
00900 " Shft-# Press to set the maximum number of unique colors in the",
00901 " image.",
00902 "",
00903 " F2 Press to reduce the speckles in an image.",
00904 "",
00905 " F3 Press to eliminate peak noise from an image.",
00906 "",
00907 " F4 Press to add noise to an image.",
00908 "",
00909 " F5 Press to sharpen an image.",
00910 "",
00911 " F6 Press to delete an image file.",
00912 "",
00913 " F7 Press to threshold the image.",
00914 "",
00915 " F8 Press to detect edges within an image.",
00916 "",
00917 " F9 Press to emboss an image.",
00918 "",
00919 " F10 Press to displace pixels by a random amount.",
00920 "",
00921 " F11 Press to negate all pixels above the threshold level.",
00922 "",
00923 " F12 Press to shade the image using a distant light source.",
00924 "",
00925 " F13 Press to lighten or darken image edges to create a 3-D effect.",
00926 "",
00927 " F14 Press to segment the image by color.",
00928 "",
00929 " Meta-S Press to swirl image pixels about the center.",
00930 "",
00931 " Meta-I Press to implode image pixels about the center.",
00932 "",
00933 " Meta-W Press to alter an image along a sine wave.",
00934 "",
00935 " Meta-P Press to simulate an oil painting.",
00936 "",
00937 " Meta-C Press to simulate a charcoal drawing.",
00938 "",
00939 " Alt-A Press to annotate the image with text.",
00940 "",
00941 " Alt-D Press to draw on an image.",
00942 "",
00943 " Alt-P Press to edit an image pixel color.",
00944 "",
00945 " Alt-M Press to edit the image matte information.",
00946 "",
00947 " Alt-V Press to composite the image with another.",
00948 "",
00949 " Alt-B Press to add a border to the image.",
00950 "",
00951 " Alt-F Press to add an ornamental border to the image.",
00952 "",
00953 " Alt-Shft-!",
00954 " Press to add an image comment.",
00955 "",
00956 " Ctl-A Press to apply image processing techniques to a region",
00957 " of interest.",
00958 "",
00959 " Shft-? Press to display information about the image.",
00960 "",
00961 " Shft-+ Press to map the zoom image window.",
00962 "",
00963 " Shft-P Press to preview an image enhancement, effect, or f/x.",
00964 "",
00965 " F1 Press to display helpful information about display(1).",
00966 "",
00967 " Find Press to browse documentation about ImageMagick.",
00968 "",
00969 " 1-9 Press to change the level of magnification.",
00970 "",
00971 " Use the arrow keys to move the image one pixel up, down,",
00972 " left, or right within the magnify window. Be sure to first",
00973 " map the magnify window by pressing button 2.",
00974 "",
00975 " Press ALT and one of the arrow keys to trim off one pixel",
00976 " from any side of the image.",
00977 (char *) NULL,
00978 },
00979 *ImageMatteEditHelp[] =
00980 {
00981 "Matte information within an image is useful for some",
00982 "operations such as image compositing (See IMAGE",
00983 "COMPOSITING). This extra channel usually defines a mask",
00984 "which represents a sort of a cookie-cutter for the image.",
00985 "This the case when matte is opaque (full coverage) for",
00986 "pixels inside the shape, zero outside, and between 0 and",
00987 "QuantumRange on the boundary.",
00988 "",
00989 "A small window appears showing the location of the cursor in",
00990 "the image window. You are now in matte edit mode. To exit",
00991 "immediately, press Dismiss. In matte edit mode, the Command",
00992 "widget has these options:",
00993 "",
00994 " Method",
00995 " point",
00996 " replace",
00997 " floodfill",
00998 " filltoborder",
00999 " reset",
01000 " Border Color",
01001 " black",
01002 " blue",
01003 " cyan",
01004 " green",
01005 " gray",
01006 " red",
01007 " magenta",
01008 " yellow",
01009 " white",
01010 " Browser...",
01011 " Fuzz",
01012 " 0%",
01013 " 2%",
01014 " 5%",
01015 " 10%",
01016 " 15%",
01017 " Dialog...",
01018 " Matte",
01019 " Opaque",
01020 " Transparent",
01021 " Dialog...",
01022 " Undo",
01023 " Help",
01024 " Dismiss",
01025 "",
01026 "Choose a matte editing method from the Method sub-menu of",
01027 "the Command widget. The point method changes the matte value",
01028 "of any pixel selected with the pointer until the button is",
01029 "is released. The replace method changes the matte value of",
01030 "any pixel that matches the color of the pixel you select with",
01031 "a button press. Floodfill changes the matte value of any pixel",
01032 "that matches the color of the pixel you select with a button",
01033 "press and is a neighbor. Whereas filltoborder changes the matte",
01034 "value any neighbor pixel that is not the border color. Finally",
01035 "reset changes the entire image to the designated matte value.",
01036 "",
01037 "Choose Matte Value and pick Opaque or Transarent. For other values",
01038 "select the Dialog entry. Here a dialog appears requesting a matte",
01039 "value. The value you select is assigned as the opacity value of the",
01040 "selected pixel or pixels.",
01041 "",
01042 "Now, press any button to select a pixel within the image",
01043 "window to change its matte value.",
01044 "",
01045 "If the Magnify widget is mapped, it can be helpful in positioning",
01046 "your pointer within the image (refer to button 2).",
01047 "",
01048 "Matte information is only valid in a DirectClass image.",
01049 "Therefore, any PseudoClass image is promoted to DirectClass",
01050 "(see miff(5)). Note that matte information for PseudoClass",
01051 "is not retained for colormapped X server visuals (e.g.",
01052 "StaticColor, StaticColor, GrayScale, PseudoColor) unless you",
01053 "immediately save your image to a file (refer to Write).",
01054 "Correct matte editing behavior may require a TrueColor or",
01055 "DirectColor visual or a Standard Colormap.",
01056 (char *) NULL,
01057 },
01058 *ImagePanHelp[] =
01059 {
01060 "When an image exceeds the width or height of the X server",
01061 "screen, display maps a small panning icon. The rectangle",
01062 "within the panning icon shows the area that is currently",
01063 "displayed in the image window. To pan about the image,",
01064 "press any button and drag the pointer within the panning",
01065 "icon. The pan rectangle moves with the pointer and the",
01066 "image window is updated to reflect the location of the",
01067 "rectangle within the panning icon. When you have selected",
01068 "the area of the image you wish to view, release the button.",
01069 "",
01070 "Use the arrow keys to pan the image one pixel up, down,",
01071 "left, or right within the image window.",
01072 "",
01073 "The panning icon is withdrawn if the image becomes smaller",
01074 "than the dimensions of the X server screen.",
01075 (char *) NULL,
01076 },
01077 *ImagePasteHelp[] =
01078 {
01079 "A small window appears showing the location of the cursor in",
01080 "the image window. You are now in paste mode. To exit",
01081 "immediately, press Dismiss. In paste mode, the Command",
01082 "widget has these options:",
01083 "",
01084 " Operators",
01085 " over",
01086 " in",
01087 " out",
01088 " atop",
01089 " xor",
01090 " plus",
01091 " minus",
01092 " add",
01093 " subtract",
01094 " difference",
01095 " replace",
01096 " Help",
01097 " Dismiss",
01098 "",
01099 "Choose a composite operation from the Operators sub-menu of",
01100 "the Command widget. How each operator behaves is described",
01101 "below. Image window is the image currently displayed on",
01102 "your X server and image is the image obtained with the File",
01103 "Browser widget.",
01104 "",
01105 "Over The result is the union of the two image shapes,",
01106 " with image obscuring image window in the region of",
01107 " overlap.",
01108 "",
01109 "In The result is simply image cut by the shape of",
01110 " image window. None of the image data of image",
01111 " window is in the result.",
01112 "",
01113 "Out The resulting image is image with the shape of",
01114 " image window cut out.",
01115 "",
01116 "Atop The result is the same shape as image image window,",
01117 " with image obscuring image window where the image",
01118 " shapes overlap. Note this differs from over",
01119 " because the portion of image outside image window's",
01120 " shape does not appear in the result.",
01121 "",
01122 "Xor The result is the image data from both image and",
01123 " image window that is outside the overlap region.",
01124 " The overlap region is blank.",
01125 "",
01126 "Plus The result is just the sum of the image data.",
01127 " Output values are cropped to QuantumRange (no overflow).",
01128 " This operation is independent of the matte",
01129 " channels.",
01130 "",
01131 "Minus The result of image - image window, with underflow",
01132 " cropped to zero.",
01133 "",
01134 "Add The result of image + image window, with overflow",
01135 " wrapping around (mod 256).",
01136 "",
01137 "Subtract The result of image - image window, with underflow",
01138 " wrapping around (mod 256). The add and subtract",
01139 " operators can be used to perform reversible",
01140 " transformations.",
01141 "",
01142 "Difference",
01143 " The result of abs(image - image window). This",
01144 " useful for comparing two very similar images.",
01145 "",
01146 "Copy The resulting image is image window replaced with",
01147 " image. Here the matte information is ignored.",
01148 "",
01149 "CopyRed The red layer of the image window is replace with",
01150 " the red layer of the image. The other layers are",
01151 " untouched.",
01152 "",
01153 "CopyGreen",
01154 " The green layer of the image window is replace with",
01155 " the green layer of the image. The other layers are",
01156 " untouched.",
01157 "",
01158 "CopyBlue The blue layer of the image window is replace with",
01159 " the blue layer of the image. The other layers are",
01160 " untouched.",
01161 "",
01162 "CopyOpacity",
01163 " The matte layer of the image window is replace with",
01164 " the matte layer of the image. The other layers are",
01165 " untouched.",
01166 "",
01167 "The image compositor requires a matte, or alpha channel in",
01168 "the image for some operations. This extra channel usually",
01169 "defines a mask which represents a sort of a cookie-cutter",
01170 "for the image. This the case when matte is opaque (full",
01171 "coverage) for pixels inside the shape, zero outside, and",
01172 "between 0 and QuantumRange on the boundary. If image does not",
01173 "have a matte channel, it is initialized with 0 for any pixel",
01174 "matching in color to pixel location (0,0), otherwise QuantumRange.",
01175 "",
01176 "Note that matte information for image window is not retained",
01177 "for colormapped X server visuals (e.g. StaticColor,",
01178 "StaticColor, GrayScale, PseudoColor). Correct compositing",
01179 "behavior may require a TrueColor or DirectColor visual or a",
01180 "Standard Colormap.",
01181 "",
01182 "Choosing a composite operator is optional. The default",
01183 "operator is replace. However, you must choose a location to",
01184 "paste your image and press button 1. Press and hold the",
01185 "button before releasing and an outline of the image will",
01186 "appear to help you identify your location.",
01187 "",
01188 "The actual colors of the pasted image is saved. However,",
01189 "the color that appears in image window may be different.",
01190 "For example, on a monochrome screen image window will appear",
01191 "black or white even though your pasted image may have",
01192 "many colors. If the image is saved to a file it is written",
01193 "with the correct colors. To assure the correct colors are",
01194 "saved in the final image, any PseudoClass image is promoted",
01195 "to DirectClass (see miff(5)). To force a PseudoClass image",
01196 "to remain PseudoClass, use -colors.",
01197 (char *) NULL,
01198 },
01199 *ImageROIHelp[] =
01200 {
01201 "In region of interest mode, the Command widget has these",
01202 "options:",
01203 "",
01204 " Help",
01205 " Dismiss",
01206 "",
01207 "To define a region of interest, press button 1 and drag.",
01208 "The region of interest is defined by a highlighted rectangle",
01209 "that expands or contracts as it follows the pointer. Once",
01210 "you are satisfied with the region of interest, release the",
01211 "button. You are now in apply mode. In apply mode the",
01212 "Command widget has these options:",
01213 "",
01214 " File",
01215 " Save...",
01216 " Print...",
01217 " Edit",
01218 " Undo",
01219 " Redo",
01220 " Transform",
01221 " Flop",
01222 " Flip",
01223 " Rotate Right",
01224 " Rotate Left",
01225 " Enhance",
01226 " Hue...",
01227 " Saturation...",
01228 " Brightness...",
01229 " Gamma...",
01230 " Spiff",
01231 " Dull",
01232 " Contrast Stretch",
01233 " Sigmoidal Contrast...",
01234 " Normalize",
01235 " Equalize",
01236 " Negate",
01237 " Grayscale",
01238 " Map...",
01239 " Quantize...",
01240 " Effects",
01241 " Despeckle",
01242 " Emboss",
01243 " Reduce Noise",
01244 " Sharpen...",
01245 " Blur...",
01246 " Threshold...",
01247 " Edge Detect...",
01248 " Spread...",
01249 " Shade...",
01250 " Raise...",
01251 " Segment...",
01252 " F/X",
01253 " Solarize...",
01254 " Sepia Tone...",
01255 " Swirl...",
01256 " Implode...",
01257 " Vignette...",
01258 " Wave...",
01259 " Oil Painting...",
01260 " Charcoal Drawing...",
01261 " Miscellany",
01262 " Image Info",
01263 " Zoom Image",
01264 " Show Preview...",
01265 " Show Histogram",
01266 " Show Matte",
01267 " Help",
01268 " Dismiss",
01269 "",
01270 "You can make adjustments to the region of interest by moving",
01271 "the pointer to one of the rectangle corners, pressing a",
01272 "button, and dragging. Finally, choose an image processing",
01273 "technique from the Command widget. You can choose more than",
01274 "one image processing technique to apply to an area.",
01275 "Alternatively, you can move the region of interest before",
01276 "applying another image processing technique. To exit, press",
01277 "Dismiss.",
01278 (char *) NULL,
01279 },
01280 *ImageRotateHelp[] =
01281 {
01282 "In rotate mode, the Command widget has these options:",
01283 "",
01284 " Pixel Color",
01285 " black",
01286 " blue",
01287 " cyan",
01288 " green",
01289 " gray",
01290 " red",
01291 " magenta",
01292 " yellow",
01293 " white",
01294 " Browser...",
01295 " Direction",
01296 " horizontal",
01297 " vertical",
01298 " Help",
01299 " Dismiss",
01300 "",
01301 "Choose a background color from the Pixel Color sub-menu.",
01302 "Additional background colors can be specified with the color",
01303 "browser. You can change the menu colors by setting the X",
01304 "resources pen1 through pen9.",
01305 "",
01306 "If you choose the color browser and press Grab, you can",
01307 "select the background color by moving the pointer to the",
01308 "desired color on the screen and press any button.",
01309 "",
01310 "Choose a point in the image window and press this button and",
01311 "hold. Next, move the pointer to another location in the",
01312 "image. As you move a line connects the initial location and",
01313 "the pointer. When you release the button, the degree of",
01314 "image rotation is determined by the slope of the line you",
01315 "just drew. The slope is relative to the direction you",
01316 "choose from the Direction sub-menu of the Command widget.",
01317 "",
01318 "To cancel the image rotation, move the pointer back to the",
01319 "starting point of the line and release the button.",
01320 (char *) NULL,
01321 };
01322
01323
01324
01325
01326 typedef enum
01327 {
01328 CopyMode,
01329 CropMode,
01330 CutMode
01331 } ClipboardMode;
01332
01333 typedef enum
01334 {
01335 OpenCommand,
01336 NextCommand,
01337 FormerCommand,
01338 SelectCommand,
01339 SaveCommand,
01340 PrintCommand,
01341 DeleteCommand,
01342 NewCommand,
01343 VisualDirectoryCommand,
01344 QuitCommand,
01345 UndoCommand,
01346 RedoCommand,
01347 CutCommand,
01348 CopyCommand,
01349 PasteCommand,
01350 HalfSizeCommand,
01351 OriginalSizeCommand,
01352 DoubleSizeCommand,
01353 ResizeCommand,
01354 ApplyCommand,
01355 RefreshCommand,
01356 RestoreCommand,
01357 CropCommand,
01358 ChopCommand,
01359 FlopCommand,
01360 FlipCommand,
01361 RotateRightCommand,
01362 RotateLeftCommand,
01363 RotateCommand,
01364 ShearCommand,
01365 RollCommand,
01366 TrimCommand,
01367 HueCommand,
01368 SaturationCommand,
01369 BrightnessCommand,
01370 GammaCommand,
01371 SpiffCommand,
01372 DullCommand,
01373 ContrastStretchCommand,
01374 SigmoidalContrastCommand,
01375 NormalizeCommand,
01376 EqualizeCommand,
01377 NegateCommand,
01378 GrayscaleCommand,
01379 MapCommand,
01380 QuantizeCommand,
01381 DespeckleCommand,
01382 EmbossCommand,
01383 ReduceNoiseCommand,
01384 AddNoiseCommand,
01385 SharpenCommand,
01386 BlurCommand,
01387 ThresholdCommand,
01388 EdgeDetectCommand,
01389 SpreadCommand,
01390 ShadeCommand,
01391 RaiseCommand,
01392 SegmentCommand,
01393 SolarizeCommand,
01394 SepiaToneCommand,
01395 SwirlCommand,
01396 ImplodeCommand,
01397 VignetteCommand,
01398 WaveCommand,
01399 OilPaintCommand,
01400 CharcoalDrawCommand,
01401 AnnotateCommand,
01402 DrawCommand,
01403 ColorCommand,
01404 MatteCommand,
01405 CompositeCommand,
01406 AddBorderCommand,
01407 AddFrameCommand,
01408 CommentCommand,
01409 LaunchCommand,
01410 RegionofInterestCommand,
01411 ROIHelpCommand,
01412 ROIDismissCommand,
01413 InfoCommand,
01414 ZoomCommand,
01415 ShowPreviewCommand,
01416 ShowHistogramCommand,
01417 ShowMatteCommand,
01418 BackgroundCommand,
01419 SlideShowCommand,
01420 PreferencesCommand,
01421 HelpCommand,
01422 BrowseDocumentationCommand,
01423 VersionCommand,
01424 SaveToUndoBufferCommand,
01425 FreeBuffersCommand,
01426 NullCommand
01427 } CommandType;
01428
01429 typedef enum
01430 {
01431 AnnotateNameCommand,
01432 AnnotateFontColorCommand,
01433 AnnotateBackgroundColorCommand,
01434 AnnotateRotateCommand,
01435 AnnotateHelpCommand,
01436 AnnotateDismissCommand,
01437 TextHelpCommand,
01438 TextApplyCommand,
01439 ChopDirectionCommand,
01440 ChopHelpCommand,
01441 ChopDismissCommand,
01442 HorizontalChopCommand,
01443 VerticalChopCommand,
01444 ColorEditMethodCommand,
01445 ColorEditColorCommand,
01446 ColorEditBorderCommand,
01447 ColorEditFuzzCommand,
01448 ColorEditUndoCommand,
01449 ColorEditHelpCommand,
01450 ColorEditDismissCommand,
01451 CompositeOperatorsCommand,
01452 CompositeDissolveCommand,
01453 CompositeDisplaceCommand,
01454 CompositeHelpCommand,
01455 CompositeDismissCommand,
01456 CropHelpCommand,
01457 CropDismissCommand,
01458 RectifyCopyCommand,
01459 RectifyHelpCommand,
01460 RectifyDismissCommand,
01461 DrawElementCommand,
01462 DrawColorCommand,
01463 DrawStippleCommand,
01464 DrawWidthCommand,
01465 DrawUndoCommand,
01466 DrawHelpCommand,
01467 DrawDismissCommand,
01468 MatteEditMethod,
01469 MatteEditBorderCommand,
01470 MatteEditFuzzCommand,
01471 MatteEditValueCommand,
01472 MatteEditUndoCommand,
01473 MatteEditHelpCommand,
01474 MatteEditDismissCommand,
01475 PasteOperatorsCommand,
01476 PasteHelpCommand,
01477 PasteDismissCommand,
01478 RotateColorCommand,
01479 RotateDirectionCommand,
01480 RotateCropCommand,
01481 RotateSharpenCommand,
01482 RotateHelpCommand,
01483 RotateDismissCommand,
01484 HorizontalRotateCommand,
01485 VerticalRotateCommand,
01486 TileLoadCommand,
01487 TileNextCommand,
01488 TileFormerCommand,
01489 TileDeleteCommand,
01490 TileUpdateCommand
01491 } ModeType;
01492
01493
01494
01495
01496 #define BricksWidth 20
01497 #define BricksHeight 20
01498 #define DiagonalWidth 16
01499 #define DiagonalHeight 16
01500 #define HighlightWidth 8
01501 #define HighlightHeight 8
01502 #define ScalesWidth 16
01503 #define ScalesHeight 16
01504 #define ShadowWidth 8
01505 #define ShadowHeight 8
01506 #define VerticalWidth 16
01507 #define VerticalHeight 16
01508 #define WavyWidth 16
01509 #define WavyHeight 16
01510
01511
01512
01513
01514 static const int
01515 RoiDelta = 8;
01516
01517 static const unsigned char
01518 BricksBitmap[] =
01519 {
01520 0xff, 0xff, 0x0f, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00,
01521 0x03, 0x0c, 0x00, 0xff, 0xff, 0x0f, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01,
01522 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0xff, 0xff, 0x0f, 0x03, 0x0c, 0x00,
01523 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0xff, 0xff, 0x0f,
01524 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01
01525 },
01526 DiagonalBitmap[] =
01527 {
01528 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22, 0x44, 0x44, 0x88, 0x88,
01529 0x11, 0x11, 0x22, 0x22, 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22,
01530 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22
01531 },
01532 ScalesBitmap[] =
01533 {
01534 0x08, 0x08, 0x08, 0x08, 0x14, 0x14, 0xe3, 0xe3, 0x80, 0x80, 0x80, 0x80,
01535 0x41, 0x41, 0x3e, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x14, 0x14, 0xe3, 0xe3,
01536 0x80, 0x80, 0x80, 0x80, 0x41, 0x41, 0x3e, 0x3e
01537 },
01538 VerticalBitmap[] =
01539 {
01540 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
01541 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
01542 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
01543 },
01544 WavyBitmap[] =
01545 {
01546 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfb, 0xff,
01547 0xe7, 0xff, 0x1f, 0xff, 0xff, 0xf8, 0xff, 0xe7, 0xff, 0xdf, 0xff, 0xbf,
01548 0xff, 0xbf, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f
01549 };
01550
01551
01552
01553
01554 static CommandType
01555 XImageWindowCommand(Display *,XResourceInfo *,XWindows *,
01556 const MagickStatusType,KeySym,Image **);
01557
01558 static Image
01559 *XMagickCommand(Display *,XResourceInfo *,XWindows *,const CommandType,
01560 Image **),
01561 *XOpenImage(Display *,XResourceInfo *,XWindows *,const MagickBooleanType),
01562 *XTileImage(Display *,XResourceInfo *,XWindows *,Image *,XEvent *),
01563 *XVisualDirectoryImage(Display *,XResourceInfo *,XWindows *);
01564
01565 static MagickBooleanType
01566 XAnnotateEditImage(Display *,XResourceInfo *,XWindows *,Image *),
01567 XDrawEditImage(Display *,XResourceInfo *,XWindows *,Image **),
01568 XChopImage(Display *,XResourceInfo *,XWindows *,Image **),
01569 XCropImage(Display *,XResourceInfo *,XWindows *,Image *,const ClipboardMode),
01570 XBackgroundImage(Display *,XResourceInfo *,XWindows *,Image **),
01571 XColorEditImage(Display *,XResourceInfo *,XWindows *,Image **),
01572 XCompositeImage(Display *,XResourceInfo *,XWindows *,Image *),
01573 XConfigureImage(Display *,XResourceInfo *,XWindows *,Image *),
01574 XMatteEditImage(Display *,XResourceInfo *,XWindows *,Image **),
01575 XPasteImage(Display *,XResourceInfo *,XWindows *,Image *),
01576 XPrintImage(Display *,XResourceInfo *,XWindows *,Image *),
01577 XRotateImage(Display *,XResourceInfo *,XWindows *,double,Image **),
01578 XROIImage(Display *,XResourceInfo *,XWindows *,Image **),
01579 XSaveImage(Display *,XResourceInfo *,XWindows *,Image *),
01580 XTrimImage(Display *,XResourceInfo *,XWindows *,Image *);
01581
01582 static void
01583 XDrawPanRectangle(Display *,XWindows *),
01584 XImageCache(Display *,XResourceInfo *,XWindows *,const CommandType,Image **),
01585 XMagnifyImage(Display *,XWindows *,XEvent *),
01586 XMakePanImage(Display *,XResourceInfo *,XWindows *,Image *),
01587 XPanImage(Display *,XWindows *,XEvent *),
01588 XMagnifyWindowCommand(Display *,XWindows *,const MagickStatusType,
01589 const KeySym),
01590 XSetCropGeometry(Display *,XWindows *,RectangleInfo *,Image *),
01591 XScreenEvent(Display *,XWindows *,XEvent *),
01592 XTranslateImage(Display *,XWindows *,Image *,const KeySym);
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621 MagickExport MagickBooleanType DisplayImages(const ImageInfo *image_info,
01622 Image *images)
01623 {
01624 char
01625 *argv[1];
01626
01627 Display
01628 *display;
01629
01630 Image
01631 *image;
01632
01633 register long
01634 i;
01635
01636 unsigned long
01637 state;
01638
01639 XrmDatabase
01640 resource_database;
01641
01642 XResourceInfo
01643 resource_info;
01644
01645 assert(image_info != (const ImageInfo *) NULL);
01646 assert(image_info->signature == MagickSignature);
01647 assert(images != (Image *) NULL);
01648 assert(images->signature == MagickSignature);
01649 if (images->debug != MagickFalse)
01650 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
01651 display=XOpenDisplay(image_info->server_name);
01652 if (display == (Display *) NULL)
01653 {
01654 (void) ThrowMagickException(&images->exception,GetMagickModule(),
01655 XServerError,"UnableToOpenXServer","`%s'",XDisplayName(
01656 image_info->server_name));
01657 return(MagickFalse);
01658 }
01659 if (images->exception.severity != UndefinedException)
01660 CatchException(&images->exception);
01661 (void) XSetErrorHandler(XError);
01662 resource_database=XGetResourceDatabase(display,GetClientName());
01663 (void) ResetMagickMemory(&resource_info,0,sizeof(resource_info));
01664 XGetResourceInfo(image_info,resource_database,GetClientName(),&resource_info);
01665 if (image_info->page != (char *) NULL)
01666 resource_info.image_geometry=AcquireString(image_info->page);
01667 resource_info.immutable=MagickTrue;
01668 argv[0]=AcquireString(GetClientName());
01669 state=DefaultState;
01670 for (i=0; (state & ExitState) == 0; i++)
01671 {
01672 image=GetImageFromList(images,i % GetImageListLength(images));
01673 (void) XDisplayImage(display,&resource_info,argv,1,&image,&state);
01674 }
01675 argv[0]=DestroyString(argv[0]);
01676 (void) XCloseDisplay(display);
01677 XDestroyResourceInfo(&resource_info);
01678 if (images->exception.severity != UndefinedException)
01679 return(MagickFalse);
01680 return(MagickTrue);
01681 }
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713 MagickExport MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
01714 const char *window,const char *filename,ExceptionInfo *exception)
01715 {
01716 Display
01717 *display;
01718
01719 MagickStatusType
01720 status;
01721
01722 assert(image_info != (const ImageInfo *) NULL);
01723 assert(image_info->signature == MagickSignature);
01724 assert(filename != (char *) NULL);
01725 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
01726 display=XOpenDisplay(image_info->server_name);
01727 if (display == (Display *) NULL)
01728 {
01729 (void) ThrowMagickException(exception,GetMagickModule(),XServerError,
01730 "UnableToOpenXServer","`%s'",XDisplayName(image_info->server_name));
01731 return(MagickFalse);
01732 }
01733 (void) XSetErrorHandler(XError);
01734 status=XRemoteCommand(display,window,filename);
01735 (void) XCloseDisplay(display);
01736 return(status != 0 ? MagickTrue : MagickFalse);
01737 }
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771 static inline long MagickMax(const long x,const long y)
01772 {
01773 if (x > y)
01774 return(x);
01775 return(y);
01776 }
01777
01778 static inline long MagickMin(const long x,const long y)
01779 {
01780 if (x < y)
01781 return(x);
01782 return(y);
01783 }
01784
01785 static MagickBooleanType XAnnotateEditImage(Display *display,
01786 XResourceInfo *resource_info,XWindows *windows,Image *image)
01787 {
01788 static const char
01789 *AnnotateMenu[] =
01790 {
01791 "Font Name",
01792 "Font Color",
01793 "Box Color",
01794 "Rotate Text",
01795 "Help",
01796 "Dismiss",
01797 (char *) NULL
01798 },
01799 *TextMenu[] =
01800 {
01801 "Help",
01802 "Apply",
01803 (char *) NULL
01804 };
01805
01806 static const ModeType
01807 AnnotateCommands[] =
01808 {
01809 AnnotateNameCommand,
01810 AnnotateFontColorCommand,
01811 AnnotateBackgroundColorCommand,
01812 AnnotateRotateCommand,
01813 AnnotateHelpCommand,
01814 AnnotateDismissCommand
01815 },
01816 TextCommands[] =
01817 {
01818 TextHelpCommand,
01819 TextApplyCommand
01820 };
01821
01822 static MagickBooleanType
01823 transparent_box = MagickTrue,
01824 transparent_pen = MagickFalse;
01825
01826 static MagickRealType
01827 degrees = 0.0;
01828
01829 static unsigned int
01830 box_id = MaxNumberPens-2,
01831 font_id = 0,
01832 pen_id = 0;
01833
01834 char
01835 command[MaxTextExtent],
01836 text[MaxTextExtent];
01837
01838 const char
01839 *ColorMenu[MaxNumberPens+1];
01840
01841 Cursor
01842 cursor;
01843
01844 GC
01845 annotate_context;
01846
01847 int
01848 id,
01849 pen_number,
01850 status,
01851 x,
01852 y;
01853
01854 KeySym
01855 key_symbol;
01856
01857 register char
01858 *p;
01859
01860 register long
01861 i;
01862
01863 unsigned int
01864 height,
01865 width;
01866
01867 unsigned long
01868 state;
01869
01870 XAnnotateInfo
01871 *annotate_info,
01872 *previous_info;
01873
01874 XColor
01875 color;
01876
01877 XFontStruct
01878 *font_info;
01879
01880 XEvent
01881 event,
01882 text_event;
01883
01884
01885
01886
01887 (void) CloneString(&windows->command.name,"Annotate");
01888 windows->command.data=4;
01889 (void) XCommandWidget(display,windows,AnnotateMenu,(XEvent *) NULL);
01890 (void) XMapRaised(display,windows->command.id);
01891 XClientMessage(display,windows->image.id,windows->im_protocols,
01892 windows->im_update_widget,CurrentTime);
01893
01894
01895
01896 XQueryPosition(display,windows->image.id,&x,&y);
01897 (void) XSelectInput(display,windows->image.id,
01898 windows->image.attributes.event_mask | PointerMotionMask);
01899 cursor=XCreateFontCursor(display,XC_left_side);
01900 (void) XCheckDefineCursor(display,windows->image.id,cursor);
01901 state=DefaultState;
01902 do
01903 {
01904 if (windows->info.mapped != MagickFalse)
01905 {
01906
01907
01908
01909 (void) FormatMagickString(text,MaxTextExtent," %+d%+d ",
01910 x+windows->image.x,y+windows->image.y);
01911 XInfoWidget(display,windows,text);
01912 }
01913
01914
01915
01916 XScreenEvent(display,windows,&event);
01917 if (event.xany.window == windows->command.id)
01918 {
01919
01920
01921
01922 id=XCommandWidget(display,windows,AnnotateMenu,&event);
01923 (void) XCheckDefineCursor(display,windows->image.id,cursor);
01924 if (id < 0)
01925 continue;
01926 switch (AnnotateCommands[id])
01927 {
01928 case AnnotateNameCommand:
01929 {
01930 const char
01931 *FontMenu[MaxNumberFonts];
01932
01933 int
01934 font_number;
01935
01936
01937
01938
01939 for (i=0; i < MaxNumberFonts; i++)
01940 FontMenu[i]=resource_info->font_name[i];
01941 FontMenu[MaxNumberFonts-2]="Browser...";
01942 FontMenu[MaxNumberFonts-1]=(const char *) NULL;
01943
01944
01945
01946 font_number=XMenuWidget(display,windows,AnnotateMenu[id],
01947 (const char **) FontMenu,command);
01948 if (font_number < 0)
01949 break;
01950 if (font_number == (MaxNumberFonts-2))
01951 {
01952 static char
01953 font_name[MaxTextExtent] = "fixed";
01954
01955
01956
01957
01958 resource_info->font_name[font_number]=font_name;
01959 XFontBrowserWidget(display,windows,"Select",font_name);
01960 if (*font_name == '\0')
01961 break;
01962 }
01963
01964
01965
01966 font_info=XLoadQueryFont(display,resource_info->font_name[
01967 font_number]);
01968 if (font_info == (XFontStruct *) NULL)
01969 {
01970 XNoticeWidget(display,windows,"Unable to load font:",
01971 resource_info->font_name[font_number]);
01972 break;
01973 }
01974 font_id=(unsigned int) font_number;
01975 (void) XFreeFont(display,font_info);
01976 break;
01977 }
01978 case AnnotateFontColorCommand:
01979 {
01980
01981
01982
01983 for (i=0; i < (int) (MaxNumberPens-2); i++)
01984 ColorMenu[i]=resource_info->pen_colors[i];
01985 ColorMenu[MaxNumberPens-2]="transparent";
01986 ColorMenu[MaxNumberPens-1]="Browser...";
01987 ColorMenu[MaxNumberPens]=(const char *) NULL;
01988
01989
01990
01991 pen_number=XMenuWidget(display,windows,AnnotateMenu[id],
01992 (const char **) ColorMenu,command);
01993 if (pen_number < 0)
01994 break;
01995 transparent_pen=pen_number == (MaxNumberPens-2) ? MagickTrue :
01996 MagickFalse;
01997 if (transparent_pen != MagickFalse)
01998 break;
01999 if (pen_number == (MaxNumberPens-1))
02000 {
02001 static char
02002 color_name[MaxTextExtent] = "gray";
02003
02004
02005
02006
02007 resource_info->pen_colors[pen_number]=color_name;
02008 XColorBrowserWidget(display,windows,"Select",color_name);
02009 if (*color_name == '\0')
02010 break;
02011 }
02012
02013
02014
02015 (void) XParseColor(display,windows->map_info->colormap,
02016 resource_info->pen_colors[pen_number],&color);
02017 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
02018 (unsigned int) MaxColors,&color);
02019 windows->pixel_info->pen_colors[pen_number]=color;
02020 pen_id=(unsigned int) pen_number;
02021 break;
02022 }
02023 case AnnotateBackgroundColorCommand:
02024 {
02025
02026
02027
02028 for (i=0; i < (int) (MaxNumberPens-2); i++)
02029 ColorMenu[i]=resource_info->pen_colors[i];
02030 ColorMenu[MaxNumberPens-2]="transparent";
02031 ColorMenu[MaxNumberPens-1]="Browser...";
02032 ColorMenu[MaxNumberPens]=(const char *) NULL;
02033
02034
02035
02036 pen_number=XMenuWidget(display,windows,AnnotateMenu[id],
02037 (const char **) ColorMenu,command);
02038 if (pen_number < 0)
02039 break;
02040 transparent_box=pen_number == (MaxNumberPens-2) ? MagickTrue :
02041 MagickFalse;
02042 if (transparent_box != MagickFalse)
02043 break;
02044 if (pen_number == (MaxNumberPens-1))
02045 {
02046 static char
02047 color_name[MaxTextExtent] = "gray";
02048
02049
02050
02051
02052 resource_info->pen_colors[pen_number]=color_name;
02053 XColorBrowserWidget(display,windows,"Select",color_name);
02054 if (*color_name == '\0')
02055 break;
02056 }
02057
02058
02059
02060 (void) XParseColor(display,windows->map_info->colormap,
02061 resource_info->pen_colors[pen_number],&color);
02062 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
02063 (unsigned int) MaxColors,&color);
02064 windows->pixel_info->pen_colors[pen_number]=color;
02065 box_id=(unsigned int) pen_number;
02066 break;
02067 }
02068 case AnnotateRotateCommand:
02069 {
02070 int
02071 entry;
02072
02073 static char
02074 angle[MaxTextExtent] = "30.0";
02075
02076 static const char
02077 *RotateMenu[] =
02078 {
02079 "-90",
02080 "-45",
02081 "-30",
02082 "0",
02083 "30",
02084 "45",
02085 "90",
02086 "180",
02087 "Dialog...",
02088 (char *) NULL,
02089 };
02090
02091
02092
02093
02094 entry=XMenuWidget(display,windows,AnnotateMenu[id],RotateMenu,
02095 command);
02096 if (entry < 0)
02097 break;
02098 if (entry != 8)
02099 {
02100 degrees=atof(RotateMenu[entry]);
02101 break;
02102 }
02103 (void) XDialogWidget(display,windows,"OK","Enter rotation angle:",
02104 angle);
02105 if (*angle == '\0')
02106 break;
02107 degrees=atof(angle);
02108 break;
02109 }
02110 case AnnotateHelpCommand:
02111 {
02112 XTextViewWidget(display,resource_info,windows,MagickFalse,
02113 "Help Viewer - Image Annotation",ImageAnnotateHelp);
02114 break;
02115 }
02116 case AnnotateDismissCommand:
02117 {
02118
02119
02120
02121 state|=EscapeState;
02122 state|=ExitState;
02123 break;
02124 }
02125 default:
02126 break;
02127 }
02128 continue;
02129 }
02130 switch (event.type)
02131 {
02132 case ButtonPress:
02133 {
02134 if (event.xbutton.button != Button1)
02135 break;
02136 if (event.xbutton.window != windows->image.id)
02137 break;
02138
02139
02140
02141 x=event.xbutton.x;
02142 y=event.xbutton.y;
02143 state|=ExitState;
02144 break;
02145 }
02146 case ButtonRelease:
02147 break;
02148 case Expose:
02149 break;
02150 case KeyPress:
02151 {
02152 if (event.xkey.window != windows->image.id)
02153 break;
02154
02155
02156
02157 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
02158 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
02159 switch ((int) key_symbol)
02160 {
02161 case XK_Escape:
02162 case XK_F20:
02163 {
02164
02165
02166
02167 state|=EscapeState;
02168 state|=ExitState;
02169 break;
02170 }
02171 case XK_F1:
02172 case XK_Help:
02173 {
02174 XTextViewWidget(display,resource_info,windows,MagickFalse,
02175 "Help Viewer - Image Annotation",ImageAnnotateHelp);
02176 break;
02177 }
02178 default:
02179 {
02180 (void) XBell(display,0);
02181 break;
02182 }
02183 }
02184 break;
02185 }
02186 case MotionNotify:
02187 {
02188
02189
02190
02191 x=event.xmotion.x;
02192 y=event.xmotion.y;
02193 if (windows->info.mapped != MagickFalse)
02194 {
02195 if ((x < (int) (windows->info.x+windows->info.width)) &&
02196 (y < (int) (windows->info.y+windows->info.height)))
02197 (void) XWithdrawWindow(display,windows->info.id,
02198 windows->info.screen);
02199 }
02200 else
02201 if ((x > (int) (windows->info.x+windows->info.width)) ||
02202 (y > (int) (windows->info.y+windows->info.height)))
02203 (void) XMapWindow(display,windows->info.id);
02204 break;
02205 }
02206 default:
02207 break;
02208 }
02209 } while ((state & ExitState) == 0);
02210 (void) XSelectInput(display,windows->image.id,
02211 windows->image.attributes.event_mask);
02212 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
02213 if ((state & EscapeState) != 0)
02214 return(MagickTrue);
02215
02216
02217
02218 font_info=XLoadQueryFont(display,resource_info->font_name[font_id]);
02219 if (font_info == (XFontStruct *) NULL)
02220 {
02221 XNoticeWidget(display,windows,"Unable to load font:",
02222 resource_info->font_name[font_id]);
02223 font_info=windows->font_info;
02224 }
02225 if ((x+font_info->max_bounds.width) >= (int) windows->image.width)
02226 x=(int) windows->image.width-font_info->max_bounds.width;
02227 if (y < (int) (font_info->ascent+font_info->descent))
02228 y=(int) font_info->ascent+font_info->descent;
02229 if (((int) font_info->max_bounds.width > (int) windows->image.width) ||
02230 ((font_info->ascent+font_info->descent) >= (int) windows->image.height))
02231 return(MagickFalse);
02232
02233
02234
02235 annotate_info=(XAnnotateInfo *) AcquireMagickMemory(sizeof(*annotate_info));
02236 if (annotate_info == (XAnnotateInfo *) NULL)
02237 return(MagickFalse);
02238 XGetAnnotateInfo(annotate_info);
02239 annotate_info->x=x;
02240 annotate_info->y=y;
02241 if ((transparent_box == MagickFalse) && (transparent_pen == MagickFalse))
02242 annotate_info->stencil=OpaqueStencil;
02243 else
02244 if (transparent_box == MagickFalse)
02245 annotate_info->stencil=BackgroundStencil;
02246 else
02247 annotate_info->stencil=ForegroundStencil;
02248 annotate_info->height=(unsigned int) font_info->ascent+font_info->descent;
02249 annotate_info->degrees=degrees;
02250 annotate_info->font_info=font_info;
02251 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
02252 windows->image.width/MagickMax(font_info->min_bounds.width,1)+2UL,
02253 sizeof(*annotate_info->text));
02254 if (annotate_info->text == (char *) NULL)
02255 return(MagickFalse);
02256
02257
02258
02259 cursor=XCreateFontCursor(display,XC_pencil);
02260 (void) XCheckDefineCursor(display,windows->image.id,cursor);
02261 annotate_context=windows->image.annotate_context;
02262 (void) XSetFont(display,annotate_context,font_info->fid);
02263 (void) XSetBackground(display,annotate_context,
02264 windows->pixel_info->pen_colors[box_id].pixel);
02265 (void) XSetForeground(display,annotate_context,
02266 windows->pixel_info->pen_colors[pen_id].pixel);
02267
02268
02269
02270 (void) CloneString(&windows->command.name,"Text");
02271 windows->command.data=0;
02272 (void) XCommandWidget(display,windows,TextMenu,(XEvent *) NULL);
02273 state=DefaultState;
02274 (void) XDrawString(display,windows->image.id,annotate_context,x,y,"_",1);
02275 text_event.xexpose.width=(int) font_info->max_bounds.width;
02276 text_event.xexpose.height=font_info->max_bounds.ascent+
02277 font_info->max_bounds.descent;
02278 p=annotate_info->text;
02279 do
02280 {
02281
02282
02283
02284 *p='\0';
02285 (void) XDrawString(display,windows->image.id,annotate_context,x,y,"_",1);
02286
02287
02288
02289 XScreenEvent(display,windows,&event);
02290 if (event.xany.window == windows->command.id)
02291 {
02292
02293
02294
02295 (void) XSetBackground(display,annotate_context,
02296 windows->pixel_info->background_color.pixel);
02297 (void) XSetForeground(display,annotate_context,
02298 windows->pixel_info->foreground_color.pixel);
02299 id=XCommandWidget(display,windows,AnnotateMenu,&event);
02300 (void) XSetBackground(display,annotate_context,
02301 windows->pixel_info->pen_colors[box_id].pixel);
02302 (void) XSetForeground(display,annotate_context,
02303 windows->pixel_info->pen_colors[pen_id].pixel);
02304 if (id < 0)
02305 continue;
02306 switch (TextCommands[id])
02307 {
02308 case TextHelpCommand:
02309 {
02310 XTextViewWidget(display,resource_info,windows,MagickFalse,
02311 "Help Viewer - Image Annotation",ImageAnnotateHelp);
02312 (void) XCheckDefineCursor(display,windows->image.id,cursor);
02313 break;
02314 }
02315 case TextApplyCommand:
02316 {
02317
02318
02319
02320 annotate_info->width=(unsigned int) XTextWidth(font_info,
02321 annotate_info->text,(int) strlen(annotate_info->text));
02322 XRefreshWindow(display,&windows->image,&text_event);
02323 state|=ExitState;
02324 break;
02325 }
02326 default:
02327 break;
02328 }
02329 continue;
02330 }
02331
02332
02333
02334 text_event.xexpose.x=x;
02335 text_event.xexpose.y=y-font_info->max_bounds.ascent;
02336 (void) XClearArea(display,windows->image.id,x,text_event.xexpose.y,
02337 (unsigned int) text_event.xexpose.width,(unsigned int)
02338 text_event.xexpose.height,MagickFalse);
02339 XRefreshWindow(display,&windows->image,&text_event);
02340 switch (event.type)
02341 {
02342 case ButtonPress:
02343 {
02344 if (event.xbutton.window != windows->image.id)
02345 break;
02346 if (event.xbutton.button == Button2)
02347 {
02348
02349
02350
02351 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
02352 windows->image.id,CurrentTime);
02353 break;
02354 }
02355 break;
02356 }
02357 case Expose:
02358 {
02359 if (event.xexpose.count == 0)
02360 {
02361 XAnnotateInfo
02362 *text_info;
02363
02364
02365
02366
02367 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
02368 text_info=annotate_info;
02369 while (text_info != (XAnnotateInfo *) NULL)
02370 {
02371 if (annotate_info->stencil == ForegroundStencil)
02372 (void) XDrawString(display,windows->image.id,annotate_context,
02373 text_info->x,text_info->y,text_info->text,
02374 (int) strlen(text_info->text));
02375 else
02376 (void) XDrawImageString(display,windows->image.id,
02377 annotate_context,text_info->x,text_info->y,text_info->text,
02378 (int) strlen(text_info->text));
02379 text_info=text_info->previous;
02380 }
02381 (void) XDrawString(display,windows->image.id,annotate_context,
02382 x,y,"_",1);
02383 }
02384 break;
02385 }
02386 case KeyPress:
02387 {
02388 int
02389 length;
02390
02391 if (event.xkey.window != windows->image.id)
02392 break;
02393
02394
02395
02396 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
02397 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
02398 *(command+length)='\0';
02399 if (((event.xkey.state & ControlMask) != 0) ||
02400 ((event.xkey.state & Mod1Mask) != 0))
02401 state|=ModifierState;
02402 if ((state & ModifierState) != 0)
02403 switch ((int) key_symbol)
02404 {
02405 case XK_u:
02406 case XK_U:
02407 {
02408 key_symbol=DeleteCommand;
02409 break;
02410 }
02411 default:
02412 break;
02413 }
02414 switch ((int) key_symbol)
02415 {
02416 case XK_BackSpace:
02417 {
02418
02419
02420
02421 if (p == annotate_info->text)
02422 {
02423 if (annotate_info->previous == (XAnnotateInfo *) NULL)
02424 break;
02425 else
02426 {
02427
02428
02429
02430 annotate_info=annotate_info->previous;
02431 p=annotate_info->text;
02432 x=annotate_info->x+annotate_info->width;
02433 y=annotate_info->y;
02434 if (annotate_info->width != 0)
02435 p+=strlen(annotate_info->text);
02436 break;
02437 }
02438 }
02439 p--;
02440 x-=XTextWidth(font_info,p,1);
02441 text_event.xexpose.x=x;
02442 text_event.xexpose.y=y-font_info->max_bounds.ascent;
02443 XRefreshWindow(display,&windows->image,&text_event);
02444 break;
02445 }
02446 case XK_bracketleft:
02447 {
02448 key_symbol=XK_Escape;
02449 break;
02450 }
02451 case DeleteCommand:
02452 {
02453
02454
02455
02456 while (p != annotate_info->text)
02457 {
02458 p--;
02459 x-=XTextWidth(font_info,p,1);
02460 text_event.xexpose.x=x;
02461 XRefreshWindow(display,&windows->image,&text_event);
02462 }
02463 break;
02464 }
02465 case XK_Escape:
02466 case XK_F20:
02467 {
02468
02469
02470
02471 annotate_info->width=(unsigned int) XTextWidth(font_info,
02472 annotate_info->text,(int) strlen(annotate_info->text));
02473 XRefreshWindow(display,&windows->image,&text_event);
02474 state|=ExitState;
02475 break;
02476 }
02477 default:
02478 {
02479
02480
02481
02482 if ((state & ModifierState) != 0)
02483 break;
02484 if (*command == '\0')
02485 break;
02486 *p=(*command);
02487 if (annotate_info->stencil == ForegroundStencil)
02488 (void) XDrawString(display,windows->image.id,annotate_context,
02489 x,y,p,1);
02490 else
02491 (void) XDrawImageString(display,windows->image.id,
02492 annotate_context,x,y,p,1);
02493 x+=XTextWidth(font_info,p,1);
02494 p++;
02495 if ((x+font_info->max_bounds.width) < (int) windows->image.width)
02496 break;
02497 }
02498 case XK_Return:
02499 case XK_KP_Enter:
02500 {
02501
02502
02503
02504 *p='\0';
02505 annotate_info->width=(unsigned int) XTextWidth(font_info,
02506 annotate_info->text,(int) strlen(annotate_info->text));
02507 if (annotate_info->next != (XAnnotateInfo *) NULL)
02508 {
02509
02510
02511
02512 annotate_info=annotate_info->next;
02513 x=annotate_info->x;
02514 y=annotate_info->y;
02515 p=annotate_info->text;
02516 break;
02517 }
02518 annotate_info->next=(XAnnotateInfo *) AcquireMagickMemory(
02519 sizeof(*annotate_info->next));
02520 if (annotate_info->next == (XAnnotateInfo *) NULL)
02521 return(MagickFalse);
02522 *annotate_info->next=(*annotate_info);
02523 annotate_info->next->previous=annotate_info;
02524 annotate_info=annotate_info->next;
02525 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
02526 windows->image.width/MagickMax(font_info->min_bounds.width,1)+2UL,
02527 sizeof(*annotate_info->text));
02528 if (annotate_info->text == (char *) NULL)
02529 return(MagickFalse);
02530 annotate_info->y+=annotate_info->height;
02531 if (annotate_info->y > (int) windows->image.height)
02532 annotate_info->y=(int) annotate_info->height;
02533 annotate_info->next=(XAnnotateInfo *) NULL;
02534 x=annotate_info->x;
02535 y=annotate_info->y;
02536 p=annotate_info->text;
02537 break;
02538 }
02539 }
02540 break;
02541 }
02542 case KeyRelease:
02543 {
02544
02545
02546
02547 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
02548 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
02549 state&=(~ModifierState);
02550 break;
02551 }
02552 case SelectionNotify:
02553 {
02554 Atom
02555 type;
02556
02557 int
02558 format;
02559
02560 unsigned char
02561 *data;
02562
02563 unsigned long
02564 after,
02565 length;
02566
02567
02568
02569
02570 if (event.xselection.property == (Atom) None)
02571 break;
02572 status=XGetWindowProperty(display,event.xselection.requestor,
02573 event.xselection.property,0L,(long) MaxTextExtent,True,XA_STRING,
02574 &type,&format,&length,&after,&data);
02575 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
02576 (length == 0))
02577 break;
02578
02579
02580
02581 for (i=0; i < (long) length; i++)
02582 {
02583 if ((char) data[i] != '\n')
02584 {
02585
02586
02587
02588 *p=(char) data[i];
02589 (void) XDrawString(display,windows->image.id,annotate_context,
02590 x,y,p,1);
02591 x+=XTextWidth(font_info,p,1);
02592 p++;
02593 if ((x+font_info->max_bounds.width) < (int) windows->image.width)
02594 continue;
02595 }
02596
02597
02598
02599 *p='\0';
02600 annotate_info->width=(unsigned int) XTextWidth(font_info,
02601 annotate_info->text,(int) strlen(annotate_info->text));
02602 if (annotate_info->next != (XAnnotateInfo *) NULL)
02603 {
02604
02605
02606
02607 annotate_info=annotate_info->next;
02608 x=annotate_info->x;
02609 y=annotate_info->y;
02610 p=annotate_info->text;
02611 continue;
02612 }
02613 annotate_info->next=(XAnnotateInfo *) AcquireMagickMemory(
02614 sizeof(*annotate_info->next));
02615 if (annotate_info->next == (XAnnotateInfo *) NULL)
02616 return(MagickFalse);
02617 *annotate_info->next=(*annotate_info);
02618 annotate_info->next->previous=annotate_info;
02619 annotate_info=annotate_info->next;
02620 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
02621 windows->image.width/MagickMax(font_info->min_bounds.width,1)+2UL,
02622 sizeof(*annotate_info->text));
02623 if (annotate_info->text == (char *) NULL)
02624 return(MagickFalse);
02625 annotate_info->y+=annotate_info->height;
02626 if (annotate_info->y > (int) windows->image.height)
02627 annotate_info->y=(int) annotate_info->height;
02628 annotate_info->next=(XAnnotateInfo *) NULL;
02629 x=annotate_info->x;
02630 y=annotate_info->y;
02631 p=annotate_info->text;
02632 }
02633 (void) XFree((void *) data);
02634 break;
02635 }
02636 default:
02637 break;
02638 }
02639 } while ((state & ExitState) == 0);
02640 (void) XFreeCursor(display,cursor);
02641
02642
02643
02644 width=(unsigned int) image->columns;
02645 height=(unsigned int) image->rows;
02646 x=0;
02647 y=0;
02648 if (windows->image.crop_geometry != (char *) NULL)
02649 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
02650
02651
02652
02653 XSetCursorState(display,windows,MagickTrue);
02654 XCheckRefreshWindows(display,windows);
02655 while (annotate_info != (XAnnotateInfo *) NULL)
02656 {
02657 if (annotate_info->width == 0)
02658 {
02659
02660
02661
02662 previous_info=annotate_info->previous;
02663 annotate_info->text=(char *)
02664 RelinquishMagickMemory(annotate_info->text);
02665 annotate_info=(XAnnotateInfo *) RelinquishMagickMemory(annotate_info);
02666 annotate_info=previous_info;
02667 continue;
02668 }
02669
02670
02671
02672 windows->pixel_info->box_color=windows->pixel_info->pen_colors[box_id];
02673 if (windows->pixel_info->colors != 0)
02674 for (i=0; i < (long) windows->pixel_info->colors; i++)
02675 if (windows->pixel_info->pixels[i] ==
02676 windows->pixel_info->pen_colors[box_id].pixel)
02677 {
02678 windows->pixel_info->box_index=(unsigned short) i;
02679 break;
02680 }
02681 windows->pixel_info->pen_color=windows->pixel_info->pen_colors[pen_id];
02682 if (windows->pixel_info->colors != 0)
02683 for (i=0; i < (long) windows->pixel_info->colors; i++)
02684 if (windows->pixel_info->pixels[i] ==
02685 windows->pixel_info->pen_colors[pen_id].pixel)
02686 {
02687 windows->pixel_info->pen_index=(unsigned short) i;
02688 break;
02689 }
02690
02691
02692
02693 annotate_info->x=(int)
02694 width*(annotate_info->x+windows->image.x)/windows->image.ximage->width;
02695 annotate_info->y=(int) height*(annotate_info->y-font_info->ascent+
02696 windows->image.y)/windows->image.ximage->height;
02697 (void) FormatMagickString(annotate_info->geometry,MaxTextExtent,
02698 "%ux%u%+d%+d",width*annotate_info->width/windows->image.ximage->width,
02699 height*annotate_info->height/windows->image.ximage->height,
02700 annotate_info->x+x,annotate_info->y+y);
02701
02702
02703
02704 status=XAnnotateImage(display,windows->pixel_info,annotate_info,image);
02705 if (status == 0)
02706 return(MagickFalse);
02707
02708
02709
02710 previous_info=annotate_info->previous;
02711 annotate_info->text=DestroyString(annotate_info->text);
02712 annotate_info=(XAnnotateInfo *) RelinquishMagickMemory(annotate_info);
02713 annotate_info=previous_info;
02714 }
02715 (void) XSetForeground(display,annotate_context,
02716 windows->pixel_info->foreground_color.pixel);
02717 (void) XSetBackground(display,annotate_context,
02718 windows->pixel_info->background_color.pixel);
02719 (void) XSetFont(display,annotate_context,windows->font_info->fid);
02720 XSetCursorState(display,windows,MagickFalse);
02721 (void) XFreeFont(display,font_info);
02722
02723
02724
02725 XConfigureImageColormap(display,resource_info,windows,image);
02726 (void) XConfigureImage(display,resource_info,windows,image);
02727 return(MagickTrue);
02728 }
02729
02730
02731
02732
02733
02734
02735
02736
02737
02738
02739
02740
02741
02742
02743
02744
02745
02746
02747
02748
02749
02750
02751
02752
02753
02754
02755
02756
02757
02758
02759
02760
02761 static MagickBooleanType XBackgroundImage(Display *display,
02762 XResourceInfo *resource_info,XWindows *windows,Image **image)
02763 {
02764 #define BackgroundImageTag "Background/Image"
02765
02766 int
02767 status;
02768
02769 static char
02770 window_id[MaxTextExtent] = "root";
02771
02772 XResourceInfo
02773 background_resources;
02774
02775
02776
02777
02778 status=XDialogWidget(display,windows,"Background",
02779 "Enter window id (id 0x00 selects window with pointer):",window_id);
02780 if (*window_id == '\0')
02781 return(MagickFalse);
02782 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image);
02783 XInfoWidget(display,windows,BackgroundImageTag);
02784 XSetCursorState(display,windows,MagickTrue);
02785 XCheckRefreshWindows(display,windows);
02786 background_resources=(*resource_info);
02787 background_resources.window_id=window_id;
02788 background_resources.backdrop=status != 0 ? MagickTrue : MagickFalse;
02789 status=XDisplayBackgroundImage(display,&background_resources,*image);
02790 if (status != MagickFalse)
02791 XClientMessage(display,windows->image.id,windows->im_protocols,
02792 windows->im_retain_colors,CurrentTime);
02793 XSetCursorState(display,windows,MagickFalse);
02794 (void) XMagickCommand(display,resource_info,windows,UndoCommand,image);
02795 return(MagickTrue);
02796 }
02797
02798
02799
02800
02801
02802
02803
02804
02805
02806
02807
02808
02809
02810
02811
02812
02813
02814
02815
02816
02817
02818
02819
02820
02821
02822
02823
02824
02825
02826
02827
02828
02829 static MagickBooleanType XChopImage(Display *display,
02830 XResourceInfo *resource_info,XWindows *windows,Image **image)
02831 {
02832 static const char
02833 *ChopMenu[] =
02834 {
02835 "Direction",
02836 "Help",
02837 "Dismiss",
02838 (char *) NULL
02839 };
02840
02841 static ModeType
02842 direction = HorizontalChopCommand;
02843
02844 static const ModeType
02845 ChopCommands[] =
02846 {
02847 ChopDirectionCommand,
02848 ChopHelpCommand,
02849 ChopDismissCommand
02850 },
02851 DirectionCommands[] =
02852 {
02853 HorizontalChopCommand,
02854 VerticalChopCommand
02855 };
02856
02857 char
02858 text[MaxTextExtent];
02859
02860 Image
02861 *chop_image;
02862
02863 int
02864 id,
02865 x,
02866 y;
02867
02868 MagickRealType
02869 scale_factor;
02870
02871 RectangleInfo
02872 chop_info;
02873
02874 unsigned int
02875 distance,
02876 height,
02877 width;
02878
02879 unsigned long
02880 state;
02881
02882 XEvent
02883 event;
02884
02885 XSegment
02886 segment_info;
02887
02888
02889
02890
02891 (void) CloneString(&windows->command.name,"Chop");
02892 windows->command.data=1;
02893 (void) XCommandWidget(display,windows,ChopMenu,(XEvent *) NULL);
02894 (void) XMapRaised(display,windows->command.id);
02895 XClientMessage(display,windows->image.id,windows->im_protocols,
02896 windows->im_update_widget,CurrentTime);
02897
02898
02899
02900 XQueryPosition(display,windows->image.id,&x,&y);
02901 (void) XSelectInput(display,windows->image.id,
02902 windows->image.attributes.event_mask | PointerMotionMask);
02903 state=DefaultState;
02904 do
02905 {
02906 if (windows->info.mapped != MagickFalse)
02907 {
02908
02909
02910
02911 (void) FormatMagickString(text,MaxTextExtent," %+d%+d ",
02912 x+windows->image.x,y+windows->image.y);
02913 XInfoWidget(display,windows,text);
02914 }
02915
02916
02917
02918 XScreenEvent(display,windows,&event);
02919 if (event.xany.window == windows->command.id)
02920 {
02921
02922
02923
02924 id=XCommandWidget(display,windows,ChopMenu,&event);
02925 if (id < 0)
02926 continue;
02927 switch (ChopCommands[id])
02928 {
02929 case ChopDirectionCommand:
02930 {
02931 char
02932 command[MaxTextExtent];
02933
02934 static const char
02935 *Directions[] =
02936 {
02937 "horizontal",
02938 "vertical",
02939 (char *) NULL,
02940 };
02941
02942
02943
02944
02945 id=XMenuWidget(display,windows,ChopMenu[id],Directions,command);
02946 if (id >= 0)
02947 direction=DirectionCommands[id];
02948 break;
02949 }
02950 case ChopHelpCommand:
02951 {
02952 XTextViewWidget(display,resource_info,windows,MagickFalse,
02953 "Help Viewer - Image Chop",ImageChopHelp);
02954 break;
02955 }
02956 case ChopDismissCommand:
02957 {
02958
02959
02960
02961 state|=EscapeState;
02962 state|=ExitState;
02963 break;
02964 }
02965 default:
02966 break;
02967 }
02968 continue;
02969 }
02970 switch (event.type)
02971 {
02972 case ButtonPress:
02973 {
02974 if (event.xbutton.button != Button1)
02975 break;
02976 if (event.xbutton.window != windows->image.id)
02977 break;
02978
02979
02980
02981 segment_info.x1=(short int) event.xbutton.x;
02982 segment_info.x2=(short int) event.xbutton.x;
02983 segment_info.y1=(short int) event.xbutton.y;
02984 segment_info.y2=(short int) event.xbutton.y;
02985 state|=ExitState;
02986 break;
02987 }
02988 case ButtonRelease:
02989 break;
02990 case Expose:
02991 break;
02992 case KeyPress:
02993 {
02994 char
02995 command[MaxTextExtent];
02996
02997 KeySym
02998 key_symbol;
02999
03000 if (event.xkey.window != windows->image.id)
03001 break;
03002
03003
03004
03005 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
03006 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
03007 switch ((int) key_symbol)
03008 {
03009 case XK_Escape:
03010 case XK_F20:
03011 {
03012
03013
03014
03015 state|=EscapeState;
03016 state|=ExitState;
03017 break;
03018 }
03019 case XK_F1:
03020 case XK_Help:
03021 {
03022 (void) XSetFunction(display,windows->image.highlight_context,
03023 GXcopy);
03024 XTextViewWidget(display,resource_info,windows,MagickFalse,
03025 "Help Viewer - Image Chop",ImageChopHelp);
03026 (void) XSetFunction(display,windows->image.highlight_context,
03027 GXinvert);
03028 break;
03029 }
03030 default:
03031 {
03032 (void) XBell(display,0);
03033 break;
03034 }
03035 }
03036 break;
03037 }
03038 case MotionNotify:
03039 {
03040
03041
03042
03043 x=event.xmotion.x;
03044 y=event.xmotion.y;
03045 if (windows->info.mapped != MagickFalse)
03046 {
03047 if ((x < (int) (windows->info.x+windows->info.width)) &&
03048 (y < (int) (windows->info.y+windows->info.height)))
03049 (void) XWithdrawWindow(display,windows->info.id,
03050 windows->info.screen);
03051 }
03052 else
03053 if ((x > (int) (windows->info.x+windows->info.width)) ||
03054 (y > (int) (windows->info.y+windows->info.height)))
03055 (void) XMapWindow(display,windows->info.id);
03056 }
03057 }
03058 } while ((state & ExitState) == 0);
03059 (void) XSelectInput(display,windows->image.id,
03060 windows->image.attributes.event_mask);
03061 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
03062 if ((state & EscapeState) != 0)
03063 return(MagickTrue);
03064
03065
03066
03067 chop_info.width=0;
03068 chop_info.height=0;
03069 chop_info.x=0;
03070 chop_info.y=0;
03071 distance=0;
03072 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
03073 state=DefaultState;
03074 do
03075 {
03076 if (distance > 9)
03077 {
03078
03079
03080
03081 if (windows->info.mapped == MagickFalse)
03082 (void) XMapWindow(display,windows->info.id);
03083 (void) FormatMagickString(text,MaxTextExtent," %lux%lu%+ld%+ld",
03084 chop_info.width,chop_info.height,chop_info.x,chop_info.y);
03085 XInfoWidget(display,windows,text);
03086 XHighlightLine(display,windows->image.id,
03087 windows->image.highlight_context,&segment_info);
03088 }
03089 else
03090 if (windows->info.mapped != MagickFalse)
03091 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
03092
03093
03094
03095 XScreenEvent(display,windows,&event);
03096 if (distance > 9)
03097 XHighlightLine(display,windows->image.id,
03098 windows->image.highlight_context,&segment_info);
03099 switch (event.type)
03100 {
03101 case ButtonPress:
03102 {
03103 segment_info.x2=(short int) event.xmotion.x;
03104 segment_info.y2=(short int) event.xmotion.y;
03105 break;
03106 }
03107 case ButtonRelease:
03108 {
03109
03110
03111
03112 segment_info.x2=(short int) event.xbutton.x;
03113 segment_info.y2=(short int) event.xbutton.y;
03114 state|=ExitState;
03115 break;
03116 }
03117 case Expose:
03118 break;
03119 case MotionNotify:
03120 {
03121 segment_info.x2=(short int) event.xmotion.x;
03122 segment_info.y2=(short int) event.xmotion.y;
03123 }
03124 default:
03125 break;
03126 }
03127
03128
03129
03130 if (segment_info.x2 < 0)
03131 segment_info.x2=0;
03132 else
03133 if (segment_info.x2 > windows->image.ximage->width)
03134 segment_info.x2=windows->image.ximage->width;
03135 if (segment_info.y2 < 0)
03136 segment_info.y2=0;
03137 else
03138 if (segment_info.y2 > windows->image.ximage->height)
03139 segment_info.y2=windows->image.ximage->height;
03140 distance=(unsigned int)
03141 (((segment_info.x2-segment_info.x1)*(segment_info.x2-segment_info.x1))+
03142 ((segment_info.y2-segment_info.y1)*(segment_info.y2-segment_info.y1)));
03143
03144
03145
03146 if (direction == HorizontalChopCommand)
03147 {
03148 chop_info.width=(unsigned long) (segment_info.x2-segment_info.x1+1);
03149 chop_info.x=windows->image.x+segment_info.x1;
03150 chop_info.height=0;
03151 chop_info.y=0;
03152 if (segment_info.x1 > (int) segment_info.x2)
03153 {
03154 chop_info.width=(unsigned long) (segment_info.x1-segment_info.x2+1);
03155 chop_info.x=windows->image.x+segment_info.x2;
03156 }
03157 }
03158 else
03159 {
03160 chop_info.width=0;
03161 chop_info.height=(unsigned long) (segment_info.y2-segment_info.y1+1);
03162 chop_info.x=0;
03163 chop_info.y=windows->image.y+segment_info.y1;
03164 if (segment_info.y1 > segment_info.y2)
03165 {
03166 chop_info.height=(unsigned long)
03167 (segment_info.y1-segment_info.y2+1);
03168 chop_info.y=windows->image.y+segment_info.y2;
03169 }
03170 }
03171 } while ((state & ExitState) == 0);
03172 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
03173 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
03174 if (distance <= 9)
03175 return(MagickTrue);
03176
03177
03178
03179 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image);
03180 XSetCursorState(display,windows,MagickTrue);
03181 XCheckRefreshWindows(display,windows);
03182 windows->image.window_changes.width=windows->image.ximage->width-
03183 (unsigned int) chop_info.width;
03184 windows->image.window_changes.height=windows->image.ximage->height-
03185 (unsigned int) chop_info.height;
03186 width=(unsigned int) (*image)->columns;
03187 height=(unsigned int) (*image)->rows;
03188 x=0;
03189 y=0;
03190 if (windows->image.crop_geometry != (char *) NULL)
03191 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
03192 scale_factor=(MagickRealType) width/windows->image.ximage->width;
03193 chop_info.x+=x;
03194 chop_info.x=(int) (scale_factor*chop_info.x+0.5);
03195 chop_info.width=(unsigned int) (scale_factor*chop_info.width+0.5);
03196 scale_factor=(MagickRealType) height/windows->image.ximage->height;
03197 chop_info.y+=y;
03198 chop_info.y=(int) (scale_factor*chop_info.y+0.5);
03199 chop_info.height=(unsigned int) (scale_factor*chop_info.height+0.5);
03200
03201
03202
03203 chop_image=ChopImage(*image,&chop_info,&(*image)->exception);
03204 XSetCursorState(display,windows,MagickFalse);
03205 if (chop_image == (Image *) NULL)
03206 return(MagickFalse);
03207 *image=DestroyImage(*image);
03208 *image=chop_image;
03209
03210
03211
03212 XConfigureImageColormap(display,resource_info,windows,*image);
03213 (void) XConfigureImage(display,resource_info,windows,*image);
03214 return(MagickTrue);
03215 }
03216
03217
03218
03219
03220
03221
03222
03223
03224
03225
03226
03227
03228
03229
03230
03231
03232
03233
03234
03235
03236
03237
03238
03239
03240
03241
03242
03243
03244
03245
03246
03247
03248
03249
03250
03251 static MagickBooleanType XColorEditImage(Display *display,
03252 XResourceInfo *resource_info,XWindows *windows,Image **image)
03253 {
03254 static const char
03255 *ColorEditMenu[] =
03256 {
03257 "Method",
03258 "Pixel Color",
03259 "Border Color",
03260 "Fuzz",
03261 "Undo",
03262 "Help",
03263 "Dismiss",
03264 (char *) NULL
03265 };
03266
03267 static const ModeType
03268 ColorEditCommands[] =
03269 {
03270 ColorEditMethodCommand,
03271 ColorEditColorCommand,
03272 ColorEditBorderCommand,
03273 ColorEditFuzzCommand,
03274 ColorEditUndoCommand,
03275 ColorEditHelpCommand,
03276 ColorEditDismissCommand
03277 };
03278
03279 static PaintMethod
03280 method = PointMethod;
03281
03282 static unsigned int
03283 pen_id = 0;
03284
03285 static XColor
03286 border_color = { 0, 0, 0, 0, 0, 0 };
03287
03288 char
03289 command[MaxTextExtent],
03290 text[MaxTextExtent];
03291
03292 Cursor
03293 cursor;
03294
03295 ExceptionInfo
03296 *exception;
03297
03298 int
03299 entry,
03300 id,
03301 x,
03302 x_offset,
03303 y,
03304 y_offset;
03305
03306 register PixelPacket
03307 *q;
03308
03309 register long
03310 i;
03311
03312 unsigned int
03313 height,
03314 width;
03315
03316 unsigned long
03317 state;
03318
03319 XColor
03320 color;
03321
03322 XEvent
03323 event;
03324
03325
03326
03327
03328 (void) CloneString(&windows->command.name,"Color Edit");
03329 windows->command.data=4;
03330 (void) XCommandWidget(display,windows,ColorEditMenu,(XEvent *) NULL);
03331 (void) XMapRaised(display,windows->command.id);
03332 XClientMessage(display,windows->image.id,windows->im_protocols,
03333 windows->im_update_widget,CurrentTime);
03334
03335
03336
03337 cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap,
03338 resource_info->background_color,resource_info->foreground_color);
03339 (void) XCheckDefineCursor(display,windows->image.id,cursor);
03340
03341
03342
03343 XQueryPosition(display,windows->image.id,&x,&y);
03344 (void) XSelectInput(display,windows->image.id,
03345 windows->image.attributes.event_mask | PointerMotionMask);
03346 state=DefaultState;
03347 do
03348 {
03349 if (windows->info.mapped != MagickFalse)
03350 {
03351
03352
03353
03354 (void) FormatMagickString(text,MaxTextExtent," %+d%+d ",
03355 x+windows->image.x,y+windows->image.y);
03356 XInfoWidget(display,windows,text);
03357 }
03358
03359
03360
03361 XScreenEvent(display,windows,&event);
03362 if (event.xany.window == windows->command.id)
03363 {
03364
03365
03366
03367 id=XCommandWidget(display,windows,ColorEditMenu,&event);
03368 if (id < 0)
03369 {
03370 (void) XCheckDefineCursor(display,windows->image.id,cursor);
03371 continue;
03372 }
03373 switch (ColorEditCommands[id])
03374 {
03375 case ColorEditMethodCommand:
03376 {
03377 char
03378 **methods;
03379
03380
03381
03382
03383 methods=(char **) GetMagickOptions(MagickMethodOptions);
03384 if (methods == (char **) NULL)
03385 break;
03386 entry=XMenuWidget(display,windows,ColorEditMenu[id],
03387 (const char **) methods,command);
03388 if (entry >= 0)
03389 method=(PaintMethod) ParseMagickOption(MagickMethodOptions,
03390 MagickFalse,methods[entry]);
03391 methods=DestroyStringList(methods);
03392 break;
03393 }
03394 case ColorEditColorCommand:
03395 {
03396 const char
03397 *ColorMenu[MaxNumberPens];
03398
03399 int
03400 pen_number;
03401
03402
03403
03404
03405 for (i=0; i < (int) (MaxNumberPens-2); i++)
03406 ColorMenu[i]=resource_info->pen_colors[i];
03407 ColorMenu[MaxNumberPens-2]="Browser...";
03408 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
03409
03410
03411
03412 pen_number=XMenuWidget(display,windows,ColorEditMenu[id],
03413 (const char **) ColorMenu,command);
03414 if (pen_number < 0)
03415 break;
03416 if (pen_number == (MaxNumberPens-2))
03417 {
03418 static char
03419 color_name[MaxTextExtent] = "gray";
03420
03421
03422
03423
03424 resource_info->pen_colors[pen_number]=color_name;
03425 XColorBrowserWidget(display,windows,"Select",color_name);
03426 if (*color_name == '\0')
03427 break;
03428 }
03429
03430
03431
03432 (void) XParseColor(display,windows->map_info->colormap,
03433 resource_info->pen_colors[pen_number],&color);
03434 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
03435 (unsigned int) MaxColors,&color);
03436 windows->pixel_info->pen_colors[pen_number]=color;
03437 pen_id=(unsigned int) pen_number;
03438 break;
03439 }
03440 case ColorEditBorderCommand:
03441 {
03442 const char
03443 *ColorMenu[MaxNumberPens];
03444
03445 int
03446 pen_number;
03447
03448
03449
03450
03451 for (i=0; i < (int) (MaxNumberPens-2); i++)
03452 ColorMenu[i]=resource_info->pen_colors[i];
03453 ColorMenu[MaxNumberPens-2]="Browser...";
03454 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
03455
03456
03457
03458 pen_number=XMenuWidget(display,windows,ColorEditMenu[id],
03459 (const char **) ColorMenu,command);
03460 if (pen_number < 0)
03461 break;
03462 if (pen_number == (MaxNumberPens-2))
03463 {
03464 static char
03465 color_name[MaxTextExtent] = "gray";
03466
03467
03468
03469
03470 resource_info->pen_colors[pen_number]=color_name;
03471 XColorBrowserWidget(display,windows,"Select",color_name);
03472 if (*color_name == '\0')
03473 break;
03474 }
03475
03476
03477
03478 (void) XParseColor(display,windows->map_info->colormap,
03479 resource_info->pen_colors[pen_number],&border_color);
03480 break;
03481 }
03482 case ColorEditFuzzCommand:
03483 {
03484 static char
03485 fuzz[MaxTextExtent];
03486
03487 static const char
03488 *FuzzMenu[] =
03489 {
03490 "0%",
03491 "2%",
03492 "5%",
03493 "10%",
03494 "15%",
03495 "Dialog...",
03496 (char *) NULL,
03497 };
03498
03499
03500
03501
03502 entry=XMenuWidget(display,windows,ColorEditMenu[id],FuzzMenu,
03503 command);
03504 if (entry < 0)
03505 break;
03506 if (entry != 5)
03507 {
03508 (*image)->fuzz=StringToDouble(FuzzMenu[entry],1.0*QuantumRange+
03509 1.0);
03510 break;
03511 }
03512 (void) (void) CopyMagickString(fuzz,"20%",MaxTextExtent);
03513 (void) XDialogWidget(display,windows,"Ok",
03514 "Enter fuzz factor (0.0 - 99.9%):",fuzz);
03515 if (*fuzz == '\0')
03516 break;
03517 (void) ConcatenateMagickString(fuzz,"%",MaxTextExtent);
03518 (*image)->fuzz=StringToDouble(fuzz,1.0*QuantumRange+1.0);
03519 break;
03520 }
03521 case ColorEditUndoCommand:
03522 {
03523 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
03524 image);
03525 break;
03526 }
03527 case ColorEditHelpCommand:
03528 default:
03529 {
03530 XTextViewWidget(display,resource_info,windows,MagickFalse,
03531 "Help Viewer - Image Annotation",ImageColorEditHelp);
03532 break;
03533 }
03534 case ColorEditDismissCommand:
03535 {
03536
03537
03538
03539 state|=EscapeState;
03540 state|=ExitState;
03541 break;
03542 }
03543 }
03544 (void) XCheckDefineCursor(display,windows->image.id,cursor);
03545 continue;
03546 }
03547 switch (event.type)
03548 {
03549 case ButtonPress:
03550 {
03551 if (event.xbutton.button != Button1)
03552 break;
03553 if ((event.xbutton.window != windows->image.id) &&
03554 (event.xbutton.window != windows->magnify.id))
03555 break;
03556
03557
03558
03559 x=event.xbutton.x;
03560 y=event.xbutton.y;
03561 (void) XMagickCommand(display,resource_info,windows,
03562 SaveToUndoBufferCommand,image);
03563 state|=UpdateConfigurationState;
03564 break;
03565 }
03566 case ButtonRelease:
03567 {
03568 if (event.xbutton.button != Button1)
03569 break;
03570 if ((event.xbutton.window != windows->image.id) &&
03571 (event.xbutton.window != windows->magnify.id))
03572 break;
03573
03574
03575
03576 x=event.xbutton.x;
03577 y=event.xbutton.y;
03578 XConfigureImageColormap(display,resource_info,windows,*image);
03579 (void) XConfigureImage(display,resource_info,windows,*image);
03580 XInfoWidget(display,windows,text);
03581 (void) XCheckDefineCursor(display,windows->image.id,cursor);
03582 state&=(~UpdateConfigurationState);
03583 break;
03584 }
03585 case Expose:
03586 break;
03587 case KeyPress:
03588 {
03589 KeySym
03590 key_symbol;
03591
03592 if (event.xkey.window == windows->magnify.id)
03593 {
03594 Window
03595 window;
03596
03597 window=windows->magnify.id;
03598 while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ;
03599 }
03600 if (event.xkey.window != windows->image.id)
03601 break;
03602
03603
03604
03605 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
03606 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
03607 switch ((int) key_symbol)
03608 {
03609 case XK_Escape:
03610 case XK_F20:
03611 {
03612
03613
03614
03615 state|=ExitState;
03616 break;
03617 }
03618 case XK_F1:
03619 case XK_Help:
03620 {
03621 XTextViewWidget(display,resource_info,windows,MagickFalse,
03622 "Help Viewer - Image Annotation",ImageColorEditHelp);
03623 break;
03624 }
03625 default:
03626 {
03627 (void) XBell(display,0);
03628 break;
03629 }
03630 }
03631 break;
03632 }
03633 case MotionNotify:
03634 {
03635
03636
03637
03638 x=event.xmotion.x;
03639 y=event.xmotion.y;
03640 if (windows->info.mapped != MagickFalse)
03641 {
03642 if ((x < (int) (windows->info.x+windows->info.width)) &&
03643 (y < (int) (windows->info.y+windows->info.height)))
03644 (void) XWithdrawWindow(display,windows->info.id,
03645 windows->info.screen);
03646 }
03647 else
03648 if ((x > (int) (windows->info.x+windows->info.width)) ||
03649 (y > (int) (windows->info.y+windows->info.height)))
03650 (void) XMapWindow(display,windows->info.id);
03651 break;
03652 }
03653 default:
03654 break;
03655 }
03656 if (event.xany.window == windows->magnify.id)
03657 {
03658 x=windows->magnify.x-windows->image.x;
03659 y=windows->magnify.y-windows->image.y;
03660 }
03661 x_offset=x;
03662 y_offset=y;
03663 if ((state & UpdateConfigurationState) != 0)
03664 {
03665 int
03666 x,
03667 y;
03668
03669
03670
03671
03672 (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1,
03673 MagickTrue);
03674 color=windows->pixel_info->pen_colors[pen_id];
03675 XPutPixel(windows->image.ximage,x_offset,y_offset,color.pixel);
03676 width=(unsigned int) (*image)->columns;
03677 height=(unsigned int) (*image)->rows;
03678 x=0;
03679 y=0;
03680 if (windows->image.crop_geometry != (char *) NULL)
03681 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
03682 &width,&height);
03683 x_offset=(int)
03684 (width*(windows->image.x+x_offset)/windows->image.ximage->width+x);
03685 y_offset=(int)
03686 (height*(windows->image.y+y_offset)/windows->image.ximage->height+y);
03687 if ((x_offset < 0) || (y_offset < 0))
03688 continue;
03689 if ((x_offset >= (long) (*image)->columns) ||
03690 (y_offset >= (long) (*image)->rows))
03691 continue;
03692 exception=(&(*image)->exception);
03693 switch (method)
03694 {
03695 case PointMethod:
03696 default:
03697 {
03698
03699
03700
03701 if (SetImageStorageClass(*image,DirectClass) == MagickFalse)
03702 return(MagickFalse);
03703 q=GetAuthenticPixels(*image,x_offset,y_offset,1,1,exception);
03704 if (q == (PixelPacket *) NULL)
03705 break;
03706 q->red=ScaleShortToQuantum(color.red);
03707 q->green=ScaleShortToQuantum(color.green);
03708 q->blue=ScaleShortToQuantum(color.blue);
03709 (void) SyncAuthenticPixels(*image,&(*image)->exception);
03710 break;
03711 }
03712 case ReplaceMethod:
03713 {
03714 PixelPacket
03715 target;
03716
03717
03718
03719
03720 (void) GetOneVirtualPixel(*image,x_offset,y_offset,&target,
03721 &(*image)->exception);
03722 if ((*image)->storage_class == DirectClass)
03723 {
03724 for (y=0; y < (long) (*image)->rows; y++)
03725 {
03726 q=GetAuthenticPixels(*image,0,y,(*image)->columns,1,exception);
03727 if (q == (PixelPacket *) NULL)
03728 break;
03729 for (x=0; x < (int) (*image)->columns; x++)
03730 {
03731 if (IsColorSimilar(*image,q,&target))
03732 {
03733 q->red=ScaleShortToQuantum(color.red);
03734 q->green=ScaleShortToQuantum(color.green);
03735 q->blue=ScaleShortToQuantum(color.blue);
03736 }
03737 q++;
03738 }
03739 if (SyncAuthenticPixels(*image,exception) == MagickFalse)
03740 break;
03741 }
03742 }
03743 else
03744 {
03745 for (i=0; i < (int) (*image)->colors; i++)
03746 if (IsColorSimilar(*image,(*image)->colormap+i,&target))
03747 {
03748 (*image)->colormap[i].red=ScaleShortToQuantum(color.red);
03749 (*image)->colormap[i].green=ScaleShortToQuantum(
03750 color.green);
03751 (*image)->colormap[i].blue=ScaleShortToQuantum(
03752 color.blue);
03753 }
03754 (void) SyncImage(*image);
03755 }
03756 break;
03757 }
03758 case FloodfillMethod:
03759 case FillToBorderMethod:
03760 {
03761 DrawInfo
03762 *draw_info;
03763
03764 MagickPixelPacket
03765 target;
03766
03767
03768
03769
03770 (void) GetOneVirtualMagickPixel(*image,x_offset,y_offset,&target,
03771 exception);
03772 if (method == FillToBorderMethod)
03773 {
03774 target.red=(MagickRealType)
03775 ScaleShortToQuantum(border_color.red);
03776 target.green=(MagickRealType)
03777 ScaleShortToQuantum(border_color.green);
03778 target.blue=(MagickRealType)
03779 ScaleShortToQuantum(border_color.blue);
03780 }
03781 draw_info=CloneDrawInfo(resource_info->image_info,
03782 (DrawInfo *) NULL);
03783 (void) QueryColorDatabase(resource_info->pen_colors[pen_id],
03784 &draw_info->fill,exception);
03785 (void) FloodfillPaintImage(*image,DefaultChannels,draw_info,&target,
03786 x_offset,y_offset,method == FloodfillMethod ? MagickFalse :
03787 MagickTrue);
03788 draw_info=DestroyDrawInfo(draw_info);
03789 break;
03790 }
03791 case ResetMethod:
03792 {
03793
03794
03795
03796 if (SetImageStorageClass(*image,DirectClass) == MagickFalse)
03797 return(MagickFalse);
03798 for (y=0; y < (long) (*image)->rows; y++)
03799 {
03800 q=QueueAuthenticPixels(*image,0,y,(*image)->columns,1,exception);
03801 if (q == (PixelPacket *) NULL)
03802 break;
03803 for (x=0; x < (int) (*image)->columns; x++)
03804 {
03805 q->red=ScaleShortToQuantum(color.red);
03806 q->green=ScaleShortToQuantum(color.green);
03807 q->blue=ScaleShortToQuantum(color.blue);
03808 q++;
03809 }
03810 if (SyncAuthenticPixels(*image,exception) == MagickFalse)
03811 break;
03812 }
03813 break;
03814 }
03815 }
03816 state&=(~UpdateConfigurationState);
03817 }
03818 } while ((state & ExitState) == 0);
03819 (void) XSelectInput(display,windows->image.id,
03820 windows->image.attributes.event_mask);
03821 XSetCursorState(display,windows,MagickFalse);
03822 (void) XFreeCursor(display,cursor);
03823 return(MagickTrue);
03824 }
03825
03826
03827
03828
03829
03830
03831
03832
03833
03834
03835
03836
03837
03838
03839
03840
03841
03842
03843
03844
03845
03846
03847
03848
03849
03850
03851
03852
03853
03854
03855
03856
03857
03858
03859 static MagickBooleanType XCompositeImage(Display *display,
03860 XResourceInfo *resource_info,XWindows *windows,Image *image)
03861 {
03862 static char
03863 displacement_geometry[MaxTextExtent] = "30x30",
03864 filename[MaxTextExtent] = "\0";
03865
03866 static const char
03867 *CompositeMenu[] =
03868 {
03869 "Operators",
03870 "Dissolve",
03871 "Displace",
03872 "Help",
03873 "Dismiss",
03874 (char *) NULL
03875 };
03876
03877 static CompositeOperator
03878 compose = CopyCompositeOp;
03879
03880 static const ModeType
03881 CompositeCommands[] =
03882 {
03883 CompositeOperatorsCommand,
03884 CompositeDissolveCommand,
03885 CompositeDisplaceCommand,
03886 CompositeHelpCommand,
03887 CompositeDismissCommand
03888 };
03889
03890 char
03891 text[MaxTextExtent];
03892
03893 Cursor
03894 cursor;
03895
03896 Image
03897 *composite_image;
03898
03899 int
03900 entry,
03901 id,
03902 x,
03903 y;
03904
03905 MagickRealType
03906 blend,
03907 scale_factor;
03908
03909 RectangleInfo
03910 highlight_info,
03911 composite_info;
03912
03913 unsigned int
03914 height,
03915 width;
03916
03917 unsigned long
03918 state;
03919
03920 XEvent
03921 event;
03922
03923
03924
03925
03926 XFileBrowserWidget(display,windows,"Composite",filename);
03927 if (*filename == '\0')
03928 return(MagickTrue);
03929
03930
03931
03932 XSetCursorState(display,windows,MagickTrue);
03933 XCheckRefreshWindows(display,windows);
03934 (void) CopyMagickString(resource_info->image_info->filename,filename,
03935 MaxTextExtent);
03936 composite_image=ReadImage(resource_info->image_info,&image->exception);
03937 CatchException(&image->exception);
03938 XSetCursorState(display,windows,MagickFalse);
03939 if (composite_image == (Image *) NULL)
03940 return(MagickFalse);
03941
03942
03943
03944 (void) CloneString(&windows->command.name,"Composite");
03945 windows->command.data=1;
03946 (void) XCommandWidget(display,windows,CompositeMenu,(XEvent *) NULL);
03947 (void) XMapRaised(display,windows->command.id);
03948 XClientMessage(display,windows->image.id,windows->im_protocols,
03949 windows->im_update_widget,CurrentTime);
03950
03951
03952
03953 XQueryPosition(display,windows->image.id,&x,&y);
03954 (void) XSelectInput(display,windows->image.id,
03955 windows->image.attributes.event_mask | PointerMotionMask);
03956 composite_info.x=windows->image.x+x;
03957 composite_info.y=windows->image.y+y;
03958 composite_info.width=0;
03959 composite_info.height=0;
03960 cursor=XCreateFontCursor(display,XC_ul_angle);
03961 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
03962 blend=0.0;
03963 state=DefaultState;
03964 do
03965 {
03966 if (windows->info.mapped != MagickFalse)
03967 {
03968
03969
03970
03971 (void) FormatMagickString(text,MaxTextExtent," %+ld%+ld ",
03972 composite_info.x,composite_info.y);
03973 XInfoWidget(display,windows,text);
03974 }
03975 highlight_info=composite_info;
03976 highlight_info.x=composite_info.x-windows->image.x;
03977 highlight_info.y=composite_info.y-windows->image.y;
03978 XHighlightRectangle(display,windows->image.id,
03979 windows->image.highlight_context,&highlight_info);
03980
03981
03982
03983 XScreenEvent(display,windows,&event);
03984 XHighlightRectangle(display,windows->image.id,
03985 windows->image.highlight_context,&highlight_info);
03986 if (event.xany.window == windows->command.id)
03987 {
03988
03989
03990
03991 id=XCommandWidget(display,windows,CompositeMenu,&event);
03992 if (id < 0)
03993 continue;
03994 switch (CompositeCommands[id])
03995 {
03996 case CompositeOperatorsCommand:
03997 {
03998 char
03999 command[MaxTextExtent],
04000 **operators;
04001
04002
04003
04004
04005 operators=GetMagickOptions(MagickComposeOptions);
04006 if (operators == (char **) NULL)
04007 break;
04008 entry=XMenuWidget(display,windows,CompositeMenu[id],
04009 (const char **) operators,command);
04010 if (entry >= 0)
04011 compose=(CompositeOperator) ParseMagickOption(
04012 MagickComposeOptions,MagickFalse,operators[entry]);
04013 operators=DestroyStringList(operators);
04014 break;
04015 }
04016 case CompositeDissolveCommand:
04017 {
04018 static char
04019 factor[MaxTextExtent] = "20.0";
04020
04021
04022
04023
04024 (void) XSetFunction(display,windows->image.highlight_context,
04025 GXcopy);
04026 (void) XDialogWidget(display,windows,"Dissolve",
04027 "Enter the blend factor (0.0 - 99.9%):",factor);
04028 (void) XSetFunction(display,windows->image.highlight_context,
04029 GXinvert);
04030 if (*factor == '\0')
04031 break;
04032 blend=atof(factor);
04033 compose=DissolveCompositeOp;
04034 break;
04035 }
04036 case CompositeDisplaceCommand:
04037 {
04038
04039
04040
04041 (void) XSetFunction(display,windows->image.highlight_context,
04042 GXcopy);
04043 (void) XDialogWidget(display,windows,"Displace",
04044 "Enter the horizontal and vertical scale:",displacement_geometry);
04045 (void) XSetFunction(display,windows->image.highlight_context,
04046 GXinvert);
04047 if (*displacement_geometry == '\0')
04048 break;
04049 compose=DisplaceCompositeOp;
04050 break;
04051 }
04052 case CompositeHelpCommand:
04053 {
04054 (void) XSetFunction(display,windows->image.highlight_context,
04055 GXcopy);
04056 XTextViewWidget(display,resource_info,windows,MagickFalse,
04057 "Help Viewer - Image Composite",ImageCompositeHelp);
04058 (void) XSetFunction(display,windows->image.highlight_context,
04059 GXinvert);
04060 break;
04061 }
04062 case CompositeDismissCommand:
04063 {
04064
04065
04066
04067 state|=EscapeState;
04068 state|=ExitState;
04069 break;
04070 }
04071 default:
04072 break;
04073 }
04074 continue;
04075 }
04076 switch (event.type)
04077 {
04078 case ButtonPress:
04079 {
04080 if (image->debug != MagickFalse)
04081 (void) LogMagickEvent(X11Event,GetMagickModule(),
04082 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
04083 event.xbutton.button,event.xbutton.x,event.xbutton.y);
04084 if (event.xbutton.button != Button1)
04085 break;
04086 if (event.xbutton.window != windows->image.id)
04087 break;
04088
04089
04090
04091 composite_info.width=composite_image->columns;
04092 composite_info.height=composite_image->rows;
04093 (void) XCheckDefineCursor(display,windows->image.id,cursor);
04094 composite_info.x=windows->image.x+event.xbutton.x;
04095 composite_info.y=windows->image.y+event.xbutton.y;
04096 break;
04097 }
04098 case ButtonRelease:
04099 {
04100 if (image->debug != MagickFalse)
04101 (void) LogMagickEvent(X11Event,GetMagickModule(),
04102 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
04103 event.xbutton.button,event.xbutton.x,event.xbutton.y);
04104 if (event.xbutton.button != Button1)
04105 break;
04106 if (event.xbutton.window != windows->image.id)
04107 break;
04108 if ((composite_info.width != 0) && (composite_info.height != 0))
04109 {
04110
04111
04112
04113 composite_info.x=windows->image.x+event.xbutton.x;
04114 composite_info.y=windows->image.y+event.xbutton.y;
04115 state|=ExitState;
04116 }
04117 break;
04118 }
04119 case Expose:
04120 break;
04121 case KeyPress:
04122 {
04123 char
04124 command[MaxTextExtent];
04125
04126 KeySym
04127 key_symbol;
04128
04129 int
04130 length;
04131
04132 if (event.xkey.window != windows->image.id)
04133 break;
04134
04135
04136
04137 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
04138 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
04139 *(command+length)='\0';
04140 if (image->debug != MagickFalse)
04141 (void) LogMagickEvent(X11Event,GetMagickModule(),
04142 "Key press: 0x%lx (%s)",(unsigned long) key_symbol,command);
04143 switch ((int) key_symbol)
04144 {
04145 case XK_Escape:
04146 case XK_F20:
04147 {
04148
04149
04150
04151 composite_image=DestroyImage(composite_image);
04152 state|=EscapeState;
04153 state|=ExitState;
04154 break;
04155 }
04156 case XK_F1:
04157 case XK_Help:
04158 {
04159 (void) XSetFunction(display,windows->image.highlight_context,
04160 GXcopy);
04161 XTextViewWidget(display,resource_info,windows,MagickFalse,
04162 "Help Viewer - Image Composite",ImageCompositeHelp);
04163 (void) XSetFunction(display,windows->image.highlight_context,
04164 GXinvert);
04165 break;
04166 }
04167 default:
04168 {
04169 (void) XBell(display,0);
04170 break;
04171 }
04172 }
04173 break;
04174 }
04175 case MotionNotify:
04176 {
04177
04178
04179
04180 x=event.xmotion.x;
04181 y=event.xmotion.y;
04182 if (windows->info.mapped != MagickFalse)
04183 {
04184 if ((x < (int) (windows->info.x+windows->info.width)) &&
04185 (y < (int) (windows->info.y+windows->info.height)))
04186 (void) XWithdrawWindow(display,windows->info.id,
04187 windows->info.screen);
04188 }
04189 else
04190 if ((x > (int) (windows->info.x+windows->info.width)) ||
04191 (y > (int) (windows->info.y+windows->info.height)))
04192 (void) XMapWindow(display,windows->info.id);
04193 composite_info.x=windows->image.x+x;
04194 composite_info.y=windows->image.y+y;
04195 break;
04196 }
04197 default:
04198 {
04199 if (image->debug != MagickFalse)
04200 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
04201 event.type);
04202 break;
04203 }
04204 }
04205 } while ((state & ExitState) == 0);
04206 (void) XSelectInput(display,windows->image.id,
04207 windows->image.attributes.event_mask);
04208 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
04209 XSetCursorState(display,windows,MagickFalse);
04210 (void) XFreeCursor(display,cursor);
04211 if ((state & EscapeState) != 0)
04212 return(MagickTrue);
04213
04214
04215
04216 XSetCursorState(display,windows,MagickTrue);
04217 XCheckRefreshWindows(display,windows);
04218 width=(unsigned int) image->columns;
04219 height=(unsigned int) image->rows;
04220 x=0;
04221 y=0;
04222 if (windows->image.crop_geometry != (char *) NULL)
04223 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
04224 scale_factor=(MagickRealType) width/windows->image.ximage->width;
04225 composite_info.x+=x;
04226 composite_info.x=(int) (scale_factor*composite_info.x+0.5);
04227 composite_info.width=(unsigned int) (scale_factor*composite_info.width+0.5);
04228 scale_factor=(MagickRealType) height/windows->image.ximage->height;
04229 composite_info.y+=y;
04230 composite_info.y=(int) (scale_factor*composite_info.y+0.5);
04231 composite_info.height=(unsigned int) (scale_factor*composite_info.height+0.5);
04232 if ((composite_info.width != composite_image->columns) ||
04233 (composite_info.height != composite_image->rows))
04234 {
04235 Image
04236 *resize_image;
04237
04238
04239
04240
04241 resize_image=ZoomImage(composite_image,composite_info.width,
04242 composite_info.height,&image->exception);
04243 composite_image=DestroyImage(composite_image);
04244 if (resize_image == (Image *) NULL)
04245 {
04246 XSetCursorState(display,windows,MagickFalse);
04247 return(MagickFalse);
04248 }
04249 composite_image=resize_image;
04250 }
04251 if (compose == DisplaceCompositeOp)
04252 (void) SetImageArtifact(composite_image,"compose:args",
04253 displacement_geometry);
04254 if (blend != 0.0)
04255 {
04256 ExceptionInfo
04257 *exception;
04258
04259 int
04260 y;
04261
04262 Quantum
04263 opacity;
04264
04265 register int
04266 x;
04267
04268 register PixelPacket
04269 *q;
04270
04271
04272
04273
04274 (void) SetImageAlphaChannel(composite_image,OpaqueAlphaChannel);
04275 opacity=(Quantum) (ScaleQuantumToChar((Quantum) QuantumRange)-
04276 ((long) ScaleQuantumToChar((Quantum) QuantumRange)*blend)/100);
04277 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
04278 return(MagickFalse);
04279 image->matte=MagickTrue;
04280 exception=(&image->exception);
04281 for (y=0; y < (long) image->rows; y++)
04282 {
04283 q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
04284 if (q == (PixelPacket *) NULL)
04285 break;
04286 for (x=0; x < (int) image->columns; x++)
04287 {
04288 q->opacity=opacity;
04289 q++;
04290 }
04291 if (SyncAuthenticPixels(image,exception) == MagickFalse)
04292 break;
04293 }
04294 }
04295
04296
04297
04298 (void) CompositeImage(image,compose,composite_image,composite_info.x,
04299 composite_info.y);
04300 composite_image=DestroyImage(composite_image);
04301 XSetCursorState(display,windows,MagickFalse);
04302
04303
04304
04305 XConfigureImageColormap(display,resource_info,windows,image);
04306 (void) XConfigureImage(display,resource_info,windows,image);
04307 return(MagickTrue);
04308 }
04309
04310
04311
04312
04313
04314
04315
04316
04317
04318
04319
04320
04321
04322
04323
04324
04325
04326
04327
04328
04329
04330
04331
04332
04333
04334
04335
04336
04337
04338
04339
04340
04341
04342
04343 static MagickBooleanType XConfigureImage(Display *display,
04344 XResourceInfo *resource_info,XWindows *windows,Image *image)
04345 {
04346 char
04347 geometry[MaxTextExtent];
04348
04349 long
04350 x,
04351 y;
04352
04353 MagickStatusType
04354 status;
04355
04356 unsigned long
04357 mask,
04358 height,
04359 width;
04360
04361 XSizeHints
04362 *size_hints;
04363
04364 XWindowChanges
04365 window_changes;
04366
04367
04368
04369
04370 width=(unsigned int) windows->image.window_changes.width;
04371 height=(unsigned int) windows->image.window_changes.height;
04372 if (image->debug != MagickFalse)
04373 (void) LogMagickEvent(X11Event,GetMagickModule(),
04374 "Configure Image: %dx%d=>%lux%lu",windows->image.ximage->width,
04375 windows->image.ximage->height,width,height);
04376 if ((width*height) == 0)
04377 return(MagickTrue);
04378 x=0;
04379 y=0;
04380
04381
04382
04383 XSetCursorState(display,windows,MagickTrue);
04384 (void) XFlush(display);
04385 if (((int) width != windows->image.ximage->width) ||
04386 ((int) height != windows->image.ximage->height))
04387 image->taint=MagickTrue;
04388 windows->magnify.x=(int)
04389 width*windows->magnify.x/windows->image.ximage->width;
04390 windows->magnify.y=(int)
04391 height*windows->magnify.y/windows->image.ximage->height;
04392 windows->image.x=(int) (width*windows->image.x/windows->image.ximage->width);
04393 windows->image.y=(int)
04394 (height*windows->image.y/windows->image.ximage->height);
04395 status=XMakeImage(display,resource_info,&windows->image,image,
04396 (unsigned int) width,(unsigned int) height);
04397 if (status == MagickFalse)
04398 XNoticeWidget(display,windows,"Unable to configure X image:",
04399 windows->image.name);
04400
04401
04402
04403 if (resource_info->image_geometry != (char *) NULL)
04404 (void) FormatMagickString(geometry,MaxTextExtent,"%s>!",
04405 resource_info->image_geometry);
04406 else
04407 (void) FormatMagickString(geometry,MaxTextExtent,"%ux%u+0+0>!",
04408 XDisplayWidth(display,windows->image.screen),
04409 XDisplayHeight(display,windows->image.screen));
04410 (void) ParseMetaGeometry(geometry,&x,&y,&width,&height);
04411 window_changes.width=(int) width;
04412 if (window_changes.width > XDisplayWidth(display,windows->image.screen))
04413 window_changes.width=XDisplayWidth(display,windows->image.screen);
04414 window_changes.height=(int) height;
04415 if (window_changes.height > XDisplayHeight(display,windows->image.screen))
04416 window_changes.height=XDisplayHeight(display,windows->image.screen);
04417 mask=(unsigned long) (CWWidth | CWHeight);
04418 if (resource_info->backdrop)
04419 {
04420 mask|=CWX | CWY;
04421 window_changes.x=(int)
04422 ((XDisplayWidth(display,windows->image.screen)/2)-(width/2));
04423 window_changes.y=(int)
04424 ((XDisplayHeight(display,windows->image.screen)/2)-(height/2));
04425 }
04426 (void) XReconfigureWMWindow(display,windows->image.id,windows->image.screen,
04427 (unsigned int) mask,&window_changes);
04428 (void) XClearWindow(display,windows->image.id);
04429 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
04430
04431
04432
04433 if (windows->magnify.mapped != MagickFalse)
04434 XMakeMagnifyImage(display,windows);
04435 windows->pan.crop_geometry=windows->image.crop_geometry;
04436 XBestIconSize(display,&windows->pan,image);
04437 while (((windows->pan.width << 1) < MaxIconSize) &&
04438 ((windows->pan.height << 1) < MaxIconSize))
04439 {
04440 windows->pan.width<<=1;
04441 windows->pan.height<<=1;
04442 }
04443 if (windows->pan.geometry != (char *) NULL)
04444 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
04445 &windows->pan.width,&windows->pan.height);
04446 window_changes.width=(int) windows->pan.width;
04447 window_changes.height=(int) windows->pan.height;
04448 size_hints=XAllocSizeHints();
04449 if (size_hints != (XSizeHints *) NULL)
04450 {
04451
04452
04453
04454 size_hints->flags=PSize | PMinSize | PMaxSize;
04455 size_hints->width=window_changes.width;
04456 size_hints->height=window_changes.height;
04457 size_hints->min_width=size_hints->width;
04458 size_hints->min_height=size_hints->height;
04459 size_hints->max_width=size_hints->width;
04460 size_hints->max_height=size_hints->height;
04461 (void) XSetNormalHints(display,windows->pan.id,size_hints);
04462 (void) XFree((void *) size_hints);
04463 }
04464 (void) XReconfigureWMWindow(display,windows->pan.id,windows->pan.screen,
04465 (unsigned int) (CWWidth | CWHeight),&window_changes);
04466
04467
04468
04469 windows->icon.crop_geometry=windows->image.crop_geometry;
04470 XBestIconSize(display,&windows->icon,image);
04471 window_changes.width=(int) windows->icon.width;
04472 window_changes.height=(int) windows->icon.height;
04473 (void) XReconfigureWMWindow(display,windows->icon.id,windows->icon.screen,
04474 (unsigned int) (CWWidth | CWHeight),&window_changes);
04475 XSetCursorState(display,windows,MagickFalse);
04476 return(status != 0 ? MagickTrue : MagickFalse);
04477 }
04478
04479
04480
04481
04482
04483
04484
04485
04486
04487
04488
04489
04490
04491
04492
04493
04494
04495
04496
04497
04498
04499
04500
04501
04502
04503
04504
04505
04506
04507
04508
04509
04510
04511
04512
04513
04514
04515
04516 static MagickBooleanType XCropImage(Display *display,
04517 XResourceInfo *resource_info,XWindows *windows,Image *image,
04518 const ClipboardMode mode)
04519 {
04520 static const char
04521 *CropModeMenu[] =
04522 {
04523 "Help",
04524 "Dismiss",
04525 (char *) NULL
04526 },
04527 *RectifyModeMenu[] =
04528 {
04529 "Crop",
04530 "Help",
04531 "Dismiss",
04532 (char *) NULL
04533 };
04534
04535 static const ModeType
04536 CropCommands[] =
04537 {
04538 CropHelpCommand,
04539 CropDismissCommand
04540 },
04541 RectifyCommands[] =
04542 {
04543 RectifyCopyCommand,
04544 RectifyHelpCommand,
04545 RectifyDismissCommand
04546 };
04547
04548 char
04549 command[MaxTextExtent],
04550 text[MaxTextExtent];
04551
04552 Cursor
04553 cursor;
04554
04555 ExceptionInfo
04556 *exception;
04557
04558 int
04559 id,
04560 x,
04561 y;
04562
04563 KeySym
04564 key_symbol;
04565
04566 Image
04567 *crop_image;
04568
04569 MagickRealType
04570 scale_factor;
04571
04572 RectangleInfo
04573 crop_info,
04574 highlight_info;
04575
04576 register PixelPacket
04577 *q;
04578
04579 unsigned int
04580 height,
04581 width;
04582
04583 unsigned long
04584 state;
04585
04586 XEvent
04587 event;
04588
04589
04590
04591
04592 switch (mode)
04593 {
04594 case CopyMode:
04595 {
04596 (void) CloneString(&windows->command.name,"Copy");
04597 break;
04598 }
04599 case CropMode:
04600 {
04601 (void) CloneString(&windows->command.name,"Crop");
04602 break;
04603 }
04604 case CutMode:
04605 {
04606 (void) CloneString(&windows->command.name,"Cut");
04607 break;
04608 }
04609 }
04610 RectifyModeMenu[0]=windows->command.name;
04611 windows->command.data=0;
04612 (void) XCommandWidget(display,windows,CropModeMenu,(XEvent *) NULL);
04613 (void) XMapRaised(display,windows->command.id);
04614 XClientMessage(display,windows->image.id,windows->im_protocols,
04615 windows->im_update_widget,CurrentTime);
04616
04617
04618
04619 XQueryPosition(display,windows->image.id,&x,&y);
04620 (void) XSelectInput(display,windows->image.id,
04621 windows->image.attributes.event_mask | PointerMotionMask);
04622 crop_info.x=windows->image.x+x;
04623 crop_info.y=windows->image.y+y;
04624 crop_info.width=0;
04625 crop_info.height=0;
04626 cursor=XCreateFontCursor(display,XC_fleur);
04627 state=DefaultState;
04628 do
04629 {
04630 if (windows->info.mapped != MagickFalse)
04631 {
04632
04633
04634
04635 (void) FormatMagickString(text,MaxTextExtent," %+ld%+ld ",
04636 crop_info.x,crop_info.y);
04637 XInfoWidget(display,windows,text);
04638 }
04639
04640
04641
04642 XScreenEvent(display,windows,&event);
04643 if (event.xany.window == windows->command.id)
04644 {
04645
04646
04647
04648 id=XCommandWidget(display,windows,CropModeMenu,&event);
04649 if (id < 0)
04650 continue;
04651 switch (CropCommands[id])
04652 {
04653 case CropHelpCommand:
04654 {
04655 switch (mode)
04656 {
04657 case CopyMode:
04658 {
04659 XTextViewWidget(display,resource_info,windows,MagickFalse,
04660 "Help Viewer - Image Copy",ImageCopyHelp);
04661 break;
04662 }
04663 case CropMode:
04664 {
04665 XTextViewWidget(display,resource_info,windows,MagickFalse,
04666 "Help Viewer - Image Crop",ImageCropHelp);
04667 break;
04668 }
04669 case CutMode:
04670 {
04671 XTextViewWidget(display,resource_info,windows,MagickFalse,
04672 "Help Viewer - Image Cut",ImageCutHelp);
04673 break;
04674 }
04675 }
04676 break;
04677 }
04678 case CropDismissCommand:
04679 {
04680
04681
04682
04683 state|=EscapeState;
04684 state|=ExitState;
04685 break;
04686 }
04687 default:
04688 break;
04689 }
04690 continue;
04691 }
04692 switch (event.type)
04693 {
04694 case ButtonPress:
04695 {
04696 if (event.xbutton.button != Button1)
04697 break;
04698 if (event.xbutton.window != windows->image.id)
04699 break;
04700
04701
04702
04703 (void) XCheckDefineCursor(display,windows->image.id,cursor);
04704 crop_info.x=windows->image.x+event.xbutton.x;
04705 crop_info.y=windows->image.y+event.xbutton.y;
04706 state|=ExitState;
04707 break;
04708 }
04709 case ButtonRelease:
04710 break;
04711 case Expose:
04712 break;
04713 case KeyPress:
04714 {
04715 if (event.xkey.window != windows->image.id)
04716 break;
04717
04718
04719
04720 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
04721 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
04722 switch ((int) key_symbol)
04723 {
04724 case XK_Escape:
04725 case XK_F20:
04726 {
04727
04728
04729
04730 state|=EscapeState;
04731 state|=ExitState;
04732 break;
04733 }
04734 case XK_F1:
04735 case XK_Help:
04736 {
04737 switch (mode)
04738 {
04739 case CopyMode:
04740 {
04741 XTextViewWidget(display,resource_info,windows,MagickFalse,
04742 "Help Viewer - Image Copy",ImageCopyHelp);
04743 break;
04744 }
04745 case CropMode:
04746 {
04747 XTextViewWidget(display,resource_info,windows,MagickFalse,
04748 "Help Viewer - Image Crop",ImageCropHelp);
04749 break;
04750 }
04751 case CutMode:
04752 {
04753 XTextViewWidget(display,resource_info,windows,MagickFalse,
04754 "Help Viewer - Image Cut",ImageCutHelp);
04755 break;
04756 }
04757 }
04758 break;
04759 }
04760 default:
04761 {
04762 (void) XBell(display,0);
04763 break;
04764 }
04765 }
04766 break;
04767 }
04768 case MotionNotify:
04769 {
04770 if (event.xmotion.window != windows->image.id)
04771 break;
04772
04773
04774
04775 x=event.xmotion.x;
04776 y=event.xmotion.y;
04777 if (windows->info.mapped != MagickFalse)
04778 {
04779 if ((x < (int) (windows->info.x+windows->info.width)) &&
04780 (y < (int) (windows->info.y+windows->info.height)))
04781 (void) XWithdrawWindow(display,windows->info.id,
04782 windows->info.screen);
04783 }
04784 else
04785 if ((x > (int) (windows->info.x+windows->info.width)) ||
04786 (y > (int) (windows->info.y+windows->info.height)))
04787 (void) XMapWindow(display,windows->info.id);
04788 crop_info.x=windows->image.x+x;
04789 crop_info.y=windows->image.y+y;
04790 break;
04791 }
04792 default:
04793 break;
04794 }
04795 } while ((state & ExitState) == 0);
04796 (void) XSelectInput(display,windows->image.id,
04797 windows->image.attributes.event_mask);
04798 if ((state & EscapeState) != 0)
04799 {
04800
04801
04802
04803 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
04804 (void) XFreeCursor(display,cursor);
04805 return(MagickTrue);
04806 }
04807 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
04808 do
04809 {
04810
04811
04812
04813 x=(int) crop_info.x;
04814 y=(int) crop_info.y;
04815 crop_info.width=0;
04816 crop_info.height=0;
04817 state=DefaultState;
04818 do
04819 {
04820 highlight_info=crop_info;
04821 highlight_info.x=crop_info.x-windows->image.x;
04822 highlight_info.y=crop_info.y-windows->image.y;
04823 if ((highlight_info.width > 3) && (highlight_info.height > 3))
04824 {
04825
04826
04827
04828 if (windows->info.mapped == MagickFalse)
04829 (void) XMapWindow(display,windows->info.id);
04830 (void) FormatMagickString(text,MaxTextExtent," %lux%lu%+ld%+ld",
04831 crop_info.width,crop_info.height,crop_info.x,crop_info.y);
04832 XInfoWidget(display,windows,text);
04833 XHighlightRectangle(display,windows->image.id,
04834 windows->image.highlight_context,&highlight_info);
04835 }
04836 else
04837 if (windows->info.mapped != MagickFalse)
04838 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
04839
04840
04841
04842 XScreenEvent(display,windows,&event);
04843 if ((highlight_info.width > 3) && (highlight_info.height > 3))
04844 XHighlightRectangle(display,windows->image.id,
04845 windows->image.highlight_context,&highlight_info);
04846 switch (event.type)
04847 {
04848 case ButtonPress:
04849 {
04850 crop_info.x=windows->image.x+event.xbutton.x;
04851 crop_info.y=windows->image.y+event.xbutton.y;
04852 break;
04853 }
04854 case ButtonRelease:
04855 {
04856
04857
04858
04859 crop_info.x=windows->image.x+event.xbutton.x;
04860 crop_info.y=windows->image.y+event.xbutton.y;
04861 XSetCursorState(display,windows,MagickFalse);
04862 state|=ExitState;
04863 windows->command.data=0;
04864 (void) XCommandWidget(display,windows,RectifyModeMenu,
04865 (XEvent *) NULL);
04866 break;
04867 }
04868 case Expose:
04869 break;
04870 case MotionNotify:
04871 {
04872 crop_info.x=windows->image.x+event.xmotion.x;
04873 crop_info.y=windows->image.y+event.xmotion.y;
04874 }
04875 default:
04876 break;
04877 }
04878 if ((((int) crop_info.x != x) && ((int) crop_info.y != y)) ||
04879 ((state & ExitState) != 0))
04880 {
04881
04882
04883
04884 if (crop_info.x < 0)
04885 crop_info.x=0;
04886 else
04887 if (crop_info.x > (int) windows->image.ximage->width)
04888 crop_info.x=windows->image.ximage->width;
04889 if ((int) crop_info.x < x)
04890 crop_info.width=(unsigned int) (x-crop_info.x);
04891 else
04892 {
04893 crop_info.width=(unsigned int) (crop_info.x-x);
04894 crop_info.x=x;
04895 }
04896 if (crop_info.y < 0)
04897 crop_info.y=0;
04898 else
04899 if (crop_info.y > (int) windows->image.ximage->height)
04900 crop_info.y=windows->image.ximage->height;
04901 if ((int) crop_info.y < y)
04902 crop_info.height=(unsigned int) (y-crop_info.y);
04903 else
04904 {
04905 crop_info.height=(unsigned int) (crop_info.y-y);
04906 crop_info.y=y;
04907 }
04908 }
04909 } while ((state & ExitState) == 0);
04910
04911
04912
04913 state=DefaultState;
04914 (void) XMapWindow(display,windows->info.id);
04915 do
04916 {
04917 if (windows->info.mapped != MagickFalse)
04918 {
04919
04920
04921
04922 (void) FormatMagickString(text,MaxTextExtent," %lux%lu%+ld%+ld",
04923 crop_info.width,crop_info.height,crop_info.x,crop_info.y);
04924 XInfoWidget(display,windows,text);
04925 }
04926 highlight_info=crop_info;
04927 highlight_info.x=crop_info.x-windows->image.x;
04928 highlight_info.y=crop_info.y-windows->image.y;
04929 if ((highlight_info.width <= 3) || (highlight_info.height <= 3))
04930 {
04931 state|=EscapeState;
04932 state|=ExitState;
04933 break;
04934 }
04935 XHighlightRectangle(display,windows->image.id,
04936 windows->image.highlight_context,&highlight_info);
04937 XScreenEvent(display,windows,&event);
04938 if (event.xany.window == windows->command.id)
04939 {
04940
04941
04942
04943 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
04944 id=XCommandWidget(display,windows,RectifyModeMenu,&event);
04945 (void) XSetFunction(display,windows->image.highlight_context,
04946 GXinvert);
04947 XHighlightRectangle(display,windows->image.id,
04948 windows->image.highlight_context,&highlight_info);
04949 if (id >= 0)
04950 switch (RectifyCommands[id])
04951 {
04952 case RectifyCopyCommand:
04953 {
04954 state|=ExitState;
04955 break;
04956 }
04957 case RectifyHelpCommand:
04958 {
04959 (void) XSetFunction(display,windows->image.highlight_context,
04960 GXcopy);
04961 switch (mode)
04962 {
04963 case CopyMode:
04964 {
04965 XTextViewWidget(display,resource_info,windows,MagickFalse,
04966 "Help Viewer - Image Copy",ImageCopyHelp);
04967 break;
04968 }
04969 case CropMode:
04970 {
04971 XTextViewWidget(display,resource_info,windows,MagickFalse,
04972 "Help Viewer - Image Crop",ImageCropHelp);
04973 break;
04974 }
04975 case CutMode:
04976 {
04977 XTextViewWidget(display,resource_info,windows,MagickFalse,
04978 "Help Viewer - Image Cut",ImageCutHelp);
04979 break;
04980 }
04981 }
04982 (void) XSetFunction(display,windows->image.highlight_context,
04983 GXinvert);
04984 break;
04985 }
04986 case RectifyDismissCommand:
04987 {
04988
04989
04990
04991 state|=EscapeState;
04992 state|=ExitState;
04993 break;
04994 }
04995 default:
04996 break;
04997 }
04998 continue;
04999 }
05000 XHighlightRectangle(display,windows->image.id,
05001 windows->image.highlight_context,&highlight_info);
05002 switch (event.type)
05003 {
05004 case ButtonPress:
05005 {
05006 if (event.xbutton.button != Button1)
05007 break;
05008 if (event.xbutton.window != windows->image.id)
05009 break;
05010 x=windows->image.x+event.xbutton.x;
05011 y=windows->image.y+event.xbutton.y;
05012 if ((x < (int) (crop_info.x+RoiDelta)) &&
05013 (x > (int) (crop_info.x-RoiDelta)) &&
05014 (y < (int) (crop_info.y+RoiDelta)) &&
05015 (y > (int) (crop_info.y-RoiDelta)))
05016 {
05017 crop_info.x=(long) (crop_info.x+crop_info.width);
05018 crop_info.y=(long) (crop_info.y+crop_info.height);
05019 state|=UpdateConfigurationState;
05020 break;
05021 }
05022 if ((x < (int) (crop_info.x+RoiDelta)) &&
05023 (x > (int) (crop_info.x-RoiDelta)) &&
05024 (y < (int) (crop_info.y+crop_info.height+RoiDelta)) &&
05025 (y > (int) (crop_info.y+crop_info.height-RoiDelta)))
05026 {
05027 crop_info.x=(long) (crop_info.x+crop_info.width);
05028 state|=UpdateConfigurationState;
05029 break;
05030 }
05031 if ((x < (int) (crop_info.x+crop_info.width+RoiDelta)) &&
05032 (x > (int) (crop_info.x+crop_info.width-RoiDelta)) &&
05033 (y < (int) (crop_info.y+RoiDelta)) &&
05034 (y > (int) (crop_info.y-RoiDelta)))
05035 {
05036 crop_info.y=(long) (crop_info.y+crop_info.height);
05037 state|=UpdateConfigurationState;
05038 break;
05039 }
05040 if ((x < (int) (crop_info.x+crop_info.width+RoiDelta)) &&
05041 (x > (int) (crop_info.x+crop_info.width-RoiDelta)) &&
05042 (y < (int) (crop_info.y+crop_info.height+RoiDelta)) &&
05043 (y > (int) (crop_info.y+crop_info.height-RoiDelta)))
05044 {
05045 state|=UpdateConfigurationState;
05046 break;
05047 }
05048 }
05049 case ButtonRelease:
05050 {
05051 if (event.xbutton.window == windows->pan.id)
05052 if ((highlight_info.x != crop_info.x-windows->image.x) ||
05053 (highlight_info.y != crop_info.y-windows->image.y))
05054 XHighlightRectangle(display,windows->image.id,
05055 windows->image.highlight_context,&highlight_info);
05056 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
05057 event.xbutton.time);
05058 break;
05059 }
05060 case Expose:
05061 {
05062 if (event.xexpose.window == windows->image.id)
05063 if (event.xexpose.count == 0)
05064 {
05065 event.xexpose.x=(int) highlight_info.x;
05066 event.xexpose.y=(int) highlight_info.y;
05067 event.xexpose.width=(int) highlight_info.width;
05068 event.xexpose.height=(int) highlight_info.height;
05069 XRefreshWindow(display,&windows->image,&event);
05070 }
05071 if (event.xexpose.window == windows->info.id)
05072 if (event.xexpose.count == 0)
05073 XInfoWidget(display,windows,text);
05074 break;
05075 }
05076 case KeyPress:
05077 {
05078 if (event.xkey.window != windows->image.id)
05079 break;
05080
05081
05082
05083 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
05084 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
05085 switch ((int) key_symbol)
05086 {
05087 case XK_Escape:
05088 case XK_F20:
05089 state|=EscapeState;
05090 case XK_Return:
05091 {
05092 state|=ExitState;
05093 break;
05094 }
05095 case XK_Home:
05096 case XK_KP_Home:
05097 {
05098 crop_info.x=(long) (windows->image.width/2L-crop_info.width/2L);
05099 crop_info.y=(long) (windows->image.height/2L-crop_info.height/2L);
05100 break;
05101 }
05102 case XK_Left:
05103 case XK_KP_Left:
05104 {
05105 crop_info.x--;
05106 break;
05107 }
05108 case XK_Up:
05109 case XK_KP_Up:
05110 case XK_Next:
05111 {
05112 crop_info.y--;
05113 break;
05114 }
05115 case XK_Right:
05116 case XK_KP_Right:
05117 {
05118 crop_info.x++;
05119 break;
05120 }
05121 case XK_Prior:
05122 case XK_Down:
05123 case XK_KP_Down:
05124 {
05125 crop_info.y++;
05126 break;
05127 }
05128 case XK_F1:
05129 case XK_Help:
05130 {
05131 (void) XSetFunction(display,windows->image.highlight_context,
05132 GXcopy);
05133 switch (mode)
05134 {
05135 case CopyMode:
05136 {
05137 XTextViewWidget(display,resource_info,windows,MagickFalse,
05138 "Help Viewer - Image Copy",ImageCopyHelp);
05139 break;
05140 }
05141 case CropMode:
05142 {
05143 XTextViewWidget(display,resource_info,windows,MagickFalse,
05144 "Help Viewer - Image Cropg",ImageCropHelp);
05145 break;
05146 }
05147 case CutMode:
05148 {
05149 XTextViewWidget(display,resource_info,windows,MagickFalse,
05150 "Help Viewer - Image Cutg",ImageCutHelp);
05151 break;
05152 }
05153 }
05154 (void) XSetFunction(display,windows->image.highlight_context,
05155 GXinvert);
05156 break;
05157 }
05158 default:
05159 {
05160 (void) XBell(display,0);
05161 break;
05162 }
05163 }
05164 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
05165 event.xkey.time);
05166 break;
05167 }
05168 case KeyRelease:
05169 break;
05170 case MotionNotify:
05171 {
05172 if (event.xmotion.window != windows->image.id)
05173 break;
05174
05175
05176
05177 x=event.xmotion.x;
05178 y=event.xmotion.y;
05179 if (windows->info.mapped != MagickFalse)
05180 {
05181 if ((x < (int) (windows->info.x+windows->info.width)) &&
05182 (y < (int) (windows->info.y+windows->info.height)))
05183 (void) XWithdrawWindow(display,windows->info.id,
05184 windows->info.screen);
05185 }
05186 else
05187 if ((x > (int) (windows->info.x+windows->info.width)) ||
05188 (y > (int) (windows->info.y+windows->info.height)))
05189 (void) XMapWindow(display,windows->info.id);
05190 crop_info.x=windows->image.x+event.xmotion.x;
05191 crop_info.y=windows->image.y+event.xmotion.y;
05192 break;
05193 }
05194 case SelectionRequest:
05195 {
05196 XSelectionEvent
05197 notify;
05198
05199 XSelectionRequestEvent
05200 *request;
05201
05202
05203
05204
05205 (void) FormatMagickString(text,MaxTextExtent,"%lux%lu%+ld%+ld",
05206 crop_info.width,crop_info.height,crop_info.x,crop_info.y);
05207 request=(&(event.xselectionrequest));
05208 (void) XChangeProperty(request->display,request->requestor,
05209 request->property,request->target,8,PropModeReplace,
05210 (unsigned char *) text,(int) strlen(text));
05211 notify.type=SelectionNotify;
05212 notify.display=request->display;
05213 notify.requestor=request->requestor;
05214 notify.selection=request->selection;
05215 notify.target=request->target;
05216 notify.time=request->time;
05217 if (request->property == None)
05218 notify.property=request->target;
05219 else
05220 notify.property=request->property;
05221 (void) XSendEvent(request->display,request->requestor,False,0,
05222 (XEvent *) ¬ify);
05223 }
05224 default:
05225 break;
05226 }
05227 if ((state & UpdateConfigurationState) != 0)
05228 {
05229 (void) XPutBackEvent(display,&event);
05230 (void) XCheckDefineCursor(display,windows->image.id,cursor);
05231 break;
05232 }
05233 } while ((state & ExitState) == 0);
05234 } while ((state & ExitState) == 0);
05235 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
05236 XSetCursorState(display,windows,MagickFalse);
05237 if ((state & EscapeState) != 0)
05238 return(MagickTrue);
05239 if (mode == CropMode)
05240 if (((int) crop_info.width != windows->image.ximage->width) ||
05241 ((int) crop_info.height != windows->image.ximage->height))
05242 {
05243
05244
05245
05246 XSetCropGeometry(display,windows,&crop_info,image);
05247 windows->image.window_changes.width=(int) crop_info.width;
05248 windows->image.window_changes.height=(int) crop_info.height;
05249 (void) XConfigureImage(display,resource_info,windows,image);
05250 return(MagickTrue);
05251 }
05252
05253
05254
05255 XSetCursorState(display,windows,MagickTrue);
05256 XCheckRefreshWindows(display,windows);
05257 width=(unsigned int) image->columns;
05258 height=(unsigned int) image->rows;
05259 x=0;
05260 y=0;
05261 if (windows->image.crop_geometry != (char *) NULL)
05262 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
05263 scale_factor=(MagickRealType) width/windows->image.ximage->width;
05264 crop_info.x+=x;
05265 crop_info.x=(int) (scale_factor*crop_info.x+0.5);
05266 crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5);
05267 scale_factor=(MagickRealType) height/windows->image.ximage->height;
05268 crop_info.y+=y;
05269 crop_info.y=(int) (scale_factor*crop_info.y+0.5);
05270 crop_info.height=(unsigned int) (scale_factor*crop_info.height+0.5);
05271 crop_image=CropImage(image,&crop_info,&image->exception);
05272 XSetCursorState(display,windows,MagickFalse);
05273 if (crop_image == (Image *) NULL)
05274 return(MagickFalse);
05275 if (resource_info->copy_image != (Image *) NULL)
05276 resource_info->copy_image=DestroyImage(resource_info->copy_image);
05277 resource_info->copy_image=crop_image;
05278 if (mode == CopyMode)
05279 {
05280 (void) XConfigureImage(display,resource_info,windows,image);
05281 return(MagickTrue);
05282 }
05283
05284
05285
05286 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
05287 return(MagickFalse);
05288 image->matte=MagickTrue;
05289 exception=(&image->exception);
05290 for (y=0; y < (long) crop_info.height; y++)
05291 {
05292 q=GetAuthenticPixels(image,crop_info.x,y+crop_info.y,crop_info.width,1,
05293 exception);
05294 if (q == (PixelPacket *) NULL)
05295 break;
05296 for (x=0; x < (int) crop_info.width; x++)
05297 {
05298 q->opacity=(Quantum) TransparentOpacity;
05299 q++;
05300 }
05301 if (SyncAuthenticPixels(image,exception) == MagickFalse)
05302 break;
05303 }
05304
05305
05306
05307 XConfigureImageColormap(display,resource_info,windows,image);
05308 (void) XConfigureImage(display,resource_info,windows,image);
05309 return(MagickTrue);
05310 }
05311
05312
05313
05314
05315
05316
05317
05318
05319
05320
05321
05322
05323
05324
05325
05326
05327
05328
05329
05330
05331
05332
05333
05334
05335
05336
05337
05338
05339
05340
05341
05342
05343
05344 static MagickBooleanType XDrawEditImage(Display *display,
05345 XResourceInfo *resource_info,XWindows *windows,Image **image)
05346 {
05347 static const char
05348 *DrawMenu[] =
05349 {
05350 "Element",
05351 "Color",
05352 "Stipple",
05353 "Width",
05354 "Undo",
05355 "Help",
05356 "Dismiss",
05357 (char *) NULL
05358 };
05359
05360 static ElementType
05361 element = PointElement;
05362
05363 static const ModeType
05364 DrawCommands[] =
05365 {
05366 DrawElementCommand,
05367 DrawColorCommand,
05368 DrawStippleCommand,
05369 DrawWidthCommand,
05370 DrawUndoCommand,
05371 DrawHelpCommand,
05372 DrawDismissCommand
05373 };
05374
05375 static Pixmap
05376 stipple = (Pixmap) NULL;
05377
05378 static unsigned int
05379 pen_id = 0,
05380 line_width = 1;
05381
05382 char
05383 command[MaxTextExtent],
05384 text[MaxTextExtent];
05385
05386 Cursor
05387 cursor;
05388
05389 int
05390 entry,
05391 id,
05392 number_coordinates,
05393 x,
05394 y;
05395
05396 MagickRealType
05397 degrees;
05398
05399 MagickStatusType
05400 status;
05401
05402 RectangleInfo
05403 rectangle_info;
05404
05405 register int
05406 i;
05407
05408 unsigned int
05409 distance,
05410 height,
05411 max_coordinates,
05412 width;
05413
05414 unsigned long
05415 state;
05416
05417 Window
05418 root_window;
05419
05420 XDrawInfo
05421 draw_info;
05422
05423 XEvent
05424 event;
05425
05426 XPoint
05427 *coordinate_info;
05428
05429 XSegment
05430 line_info;
05431
05432
05433
05434
05435 max_coordinates=2048;
05436 coordinate_info=(XPoint *) AcquireQuantumMemory((size_t) max_coordinates,
05437 sizeof(*coordinate_info));
05438 if (coordinate_info == (XPoint *) NULL)
05439 {
05440 (void) ThrowMagickException(&(*image)->exception,GetMagickModule(),
05441 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
05442 return(MagickFalse);
05443 }
05444
05445
05446
05447 (void) CloneString(&windows->command.name,"Draw");
05448 windows->command.data=4;
05449 (void) XCommandWidget(display,windows,DrawMenu,(XEvent *) NULL);
05450 (void) XMapRaised(display,windows->command.id);
05451 XClientMessage(display,windows->image.id,windows->im_protocols,
05452 windows->im_update_widget,CurrentTime);
05453
05454
05455
05456 root_window=XRootWindow(display,XDefaultScreen(display));
05457 draw_info.stencil=OpaqueStencil;
05458 status=MagickTrue;
05459 cursor=XCreateFontCursor(display,XC_tcross);
05460 for ( ; ; )
05461 {
05462 XQueryPosition(display,windows->image.id,&x,&y);
05463 (void) XSelectInput(display,windows->image.id,
05464 windows->image.attributes.event_mask | PointerMotionMask);
05465 (void) XCheckDefineCursor(display,windows->image.id,cursor);
05466 state=DefaultState;
05467 do
05468 {
05469 if (windows->info.mapped != MagickFalse)
05470 {
05471
05472
05473
05474 (void) FormatMagickString(text,MaxTextExtent," %+d%+d ",
05475 x+windows->image.x,y+windows->image.y);
05476 XInfoWidget(display,windows,text);
05477 }
05478
05479
05480
05481 XScreenEvent(display,windows,&event);
05482 if (event.xany.window == windows->command.id)
05483 {
05484
05485
05486
05487 id=XCommandWidget(display,windows,DrawMenu,&event);
05488 if (id < 0)
05489 continue;
05490 switch (DrawCommands[id])
05491 {
05492 case DrawElementCommand:
05493 {
05494 static const char
05495 *Elements[] =
05496 {
05497 "point",
05498 "line",
05499 "rectangle",
05500 "fill rectangle",
05501 "circle",
05502 "fill circle",
05503 "ellipse",
05504 "fill ellipse",
05505 "polygon",
05506 "fill polygon",
05507 (char *) NULL,
05508 };
05509
05510
05511
05512
05513 element=(ElementType) (XMenuWidget(display,windows,
05514 DrawMenu[id],Elements,command)+1);
05515 break;
05516 }
05517 case DrawColorCommand:
05518 {
05519 const char
05520 *ColorMenu[MaxNumberPens+1];
05521
05522 int
05523 pen_number;
05524
05525 MagickBooleanType
05526 transparent;
05527
05528 XColor
05529 color;
05530
05531
05532
05533
05534 for (i=0; i < (int) (MaxNumberPens-2); i++)
05535 ColorMenu[i]=resource_info->pen_colors[i];
05536 ColorMenu[MaxNumberPens-2]="transparent";
05537 ColorMenu[MaxNumberPens-1]="Browser...";
05538 ColorMenu[MaxNumberPens]=(char *) NULL;
05539
05540
05541
05542 pen_number=XMenuWidget(display,windows,DrawMenu[id],
05543 (const char **) ColorMenu,command);
05544 if (pen_number < 0)
05545 break;
05546 transparent=pen_number == (MaxNumberPens-2) ? MagickTrue :
05547 MagickFalse;
05548 if (transparent != MagickFalse)
05549 {
05550 draw_info.stencil=TransparentStencil;
05551 break;
05552 }
05553 if (pen_number == (MaxNumberPens-1))
05554 {
05555 static char
05556 color_name[MaxTextExtent] = "gray";
05557
05558
05559
05560
05561 resource_info->pen_colors[pen_number]=color_name;
05562 XColorBrowserWidget(display,windows,"Select",color_name);
05563 if (*color_name == '\0')
05564 break;
05565 }
05566
05567
05568
05569 (void) XParseColor(display,windows->map_info->colormap,
05570 resource_info->pen_colors[pen_number],&color);
05571 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
05572 (unsigned int) MaxColors,&color);
05573 windows->pixel_info->pen_colors[pen_number]=color;
05574 pen_id=(unsigned int) pen_number;
05575 draw_info.stencil=OpaqueStencil;
05576 break;
05577 }
05578 case DrawStippleCommand:
05579 {
05580 Image
05581 *stipple_image;
05582
05583 ImageInfo
05584 *image_info;
05585
05586 int
05587 status;
05588
05589 static char
05590 filename[MaxTextExtent] = "\0";
05591
05592 static const char
05593 *StipplesMenu[] =
05594 {
05595 "Brick",
05596 "Diagonal",
05597 "Scales",
05598 "Vertical",
05599 "Wavy",
05600 "Translucent",
05601 "Opaque",
05602 (char *) NULL,
05603 (char *) NULL,
05604 };
05605
05606
05607
05608
05609 StipplesMenu[7]="Open...";
05610 entry=XMenuWidget(display,windows,DrawMenu[id],StipplesMenu,
05611 command);
05612 if (entry < 0)
05613 break;
05614 if (stipple != (Pixmap) NULL)
05615 (void) XFreePixmap(display,stipple);
05616 stipple=(Pixmap) NULL;
05617 if (entry == 6)
05618 break;
05619 if (entry != 7)
05620 {
05621 switch (entry)
05622 {
05623 case 0:
05624 {
05625 stipple=XCreateBitmapFromData(display,root_window,
05626 (char *) BricksBitmap,BricksWidth,BricksHeight);
05627 break;
05628 }
05629 case 1:
05630 {
05631 stipple=XCreateBitmapFromData(display,root_window,
05632 (char *) DiagonalBitmap,DiagonalWidth,DiagonalHeight);
05633 break;
05634 }
05635 case 2:
05636 {
05637 stipple=XCreateBitmapFromData(display,root_window,
05638 (char *) ScalesBitmap,ScalesWidth,ScalesHeight);
05639 break;
05640 }
05641 case 3:
05642 {
05643 stipple=XCreateBitmapFromData(display,root_window,
05644 (char *) VerticalBitmap,VerticalWidth,VerticalHeight);
05645 break;
05646 }
05647 case 4:
05648 {
05649 stipple=XCreateBitmapFromData(display,root_window,
05650 (char *) WavyBitmap,WavyWidth,WavyHeight);
05651 break;
05652 }
05653 case 5:
05654 default:
05655 {
05656 stipple=XCreateBitmapFromData(display,root_window,
05657 (char *) HighlightBitmap,HighlightWidth,
05658 HighlightHeight);
05659 break;
05660 }
05661 }
05662 break;
05663 }
05664 XFileBrowserWidget(display,windows,"Stipple",filename);
05665 if (*filename == '\0')
05666 break;
05667
05668
05669
05670 XSetCursorState(display,windows,MagickTrue);
05671 XCheckRefreshWindows(display,windows);
05672 image_info=AcquireImageInfo();
05673 (void) CopyMagickString(image_info->filename,filename,
05674 MaxTextExtent);
05675 stipple_image=ReadImage(image_info,&(*image)->exception);
05676 CatchException(&(*image)->exception);
05677 XSetCursorState(display,windows,MagickFalse);
05678 if (stipple_image == (Image *) NULL)
05679 break;
05680 (void) AcquireUniqueFileResource(filename);
05681 (void) FormatMagickString(stipple_image->filename,MaxTextExtent,
05682 "xbm:%s",filename);
05683 (void) WriteImage(image_info,stipple_image);
05684 stipple_image=DestroyImage(stipple_image);
05685 image_info=DestroyImageInfo(image_info);
05686 status=XReadBitmapFile(display,root_window,filename,&width,
05687 &height,&stipple,&x,&y);
05688 (void) RelinquishUniqueFileResource(filename);
05689 if ((status != BitmapSuccess) != 0)
05690 XNoticeWidget(display,windows,"Unable to read X bitmap image:",
05691 filename);
05692 break;
05693 }
05694 case DrawWidthCommand:
05695 {
05696 static char
05697 width[MaxTextExtent] = "0";
05698
05699 static const char
05700 *WidthsMenu[] =
05701 {
05702 "1",
05703 "2",
05704 "4",
05705 "8",
05706 "16",
05707 "Dialog...",
05708 (char *) NULL,
05709 };
05710
05711
05712
05713
05714 entry=XMenuWidget(display,windows,DrawMenu[id],WidthsMenu,
05715 command);
05716 if (entry < 0)
05717 break;
05718 if (entry != 5)
05719 {
05720 line_width=(unsigned int) atoi(WidthsMenu[entry]);
05721 break;
05722 }
05723 (void) XDialogWidget(display,windows,"Ok","Enter line width:",
05724 width);
05725 if (*width == '\0')
05726 break;
05727 line_width=(unsigned int) atoi(width);
05728 break;
05729 }
05730 case DrawUndoCommand:
05731 {
05732 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
05733 image);
05734 break;
05735 }
05736 case DrawHelpCommand:
05737 {
05738 XTextViewWidget(display,resource_info,windows,MagickFalse,
05739 "Help Viewer - Image Rotation",ImageDrawHelp);
05740 (void) XCheckDefineCursor(display,windows->image.id,cursor);
05741 break;
05742 }
05743 case DrawDismissCommand:
05744 {
05745
05746
05747
05748 state|=EscapeState;
05749 state|=ExitState;
05750 break;
05751 }
05752 default:
05753 break;
05754 }
05755 (void) XCheckDefineCursor(display,windows->image.id,cursor);
05756 continue;
05757 }
05758 switch (event.type)
05759 {
05760 case ButtonPress:
05761 {
05762 if (event.xbutton.button != Button1)
05763 break;
05764 if (event.xbutton.window != windows->image.id)
05765 break;
05766
05767
05768
05769 x=event.xbutton.x;
05770 y=event.xbutton.y;
05771 state|=ExitState;
05772 break;
05773 }
05774 case ButtonRelease:
05775 break;
05776 case Expose:
05777 break;
05778 case KeyPress:
05779 {
05780 KeySym
05781 key_symbol;
05782
05783 if (event.xkey.window != windows->image.id)
05784 break;
05785
05786
05787
05788 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
05789 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
05790 switch ((int) key_symbol)
05791 {
05792 case XK_Escape:
05793 case XK_F20:
05794 {
05795
05796
05797
05798 state|=EscapeState;
05799 state|=ExitState;
05800 break;
05801 }
05802 case XK_F1:
05803 case XK_Help:
05804 {
05805 XTextViewWidget(display,resource_info,windows,MagickFalse,
05806 "Help Viewer - Image Rotation",ImageDrawHelp);
05807 break;
05808 }
05809 default:
05810 {
05811 (void) XBell(display,0);
05812 break;
05813 }
05814 }
05815 break;
05816 }
05817 case MotionNotify:
05818 {
05819
05820
05821
05822 x=event.xmotion.x;
05823 y=event.xmotion.y;
05824 if (windows->info.mapped != MagickFalse)
05825 {
05826 if ((x < (int) (windows->info.x+windows->info.width)) &&
05827 (y < (int) (windows->info.y+windows->info.height)))
05828 (void) XWithdrawWindow(display,windows->info.id,
05829 windows->info.screen);
05830 }
05831 else
05832 if ((x > (int) (windows->info.x+windows->info.width)) ||
05833 (y > (int) (windows->info.y+windows->info.height)))
05834 (void) XMapWindow(display,windows->info.id);
05835 break;
05836 }
05837 }
05838 } while ((state & ExitState) == 0);
05839 (void) XSelectInput(display,windows->image.id,
05840 windows->image.attributes.event_mask);
05841 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
05842 if ((state & EscapeState) != 0)
05843 break;
05844
05845
05846
05847 distance=0;
05848 degrees=0.0;
05849 line_info.x1=x;
05850 line_info.y1=y;
05851 line_info.x2=x;
05852 line_info.y2=y;
05853 rectangle_info.x=x;
05854 rectangle_info.y=y;
05855 rectangle_info.width=0;
05856 rectangle_info.height=0;
05857 number_coordinates=1;
05858 coordinate_info->x=x;
05859 coordinate_info->y=y;
05860 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
05861 state=DefaultState;
05862 do
05863 {
05864 switch (element)
05865 {
05866 case PointElement:
05867 default:
05868 {
05869 if (number_coordinates > 1)
05870 {
05871 (void) XDrawLines(display,windows->image.id,
05872 windows->image.highlight_context,coordinate_info,
05873 number_coordinates,CoordModeOrigin);
05874 (void) FormatMagickString(text,MaxTextExtent," %+d%+d",
05875 coordinate_info[number_coordinates-1].x,
05876 coordinate_info[number_coordinates-1].y);
05877 XInfoWidget(display,windows,text);
05878 }
05879 break;
05880 }
05881 case LineElement:
05882 {
05883 if (distance > 9)
05884 {
05885
05886
05887
05888 degrees=RadiansToDegrees(-atan2((double) (line_info.y2-
05889 line_info.y1),(double) (line_info.x2-line_info.x1)));
05890 (void) FormatMagickString(text,MaxTextExtent," %g",
05891 (double) degrees);
05892 XInfoWidget(display,windows,text);
05893 XHighlightLine(display,windows->image.id,
05894 windows->image.highlight_context,&line_info);
05895 }
05896 else
05897 if (windows->info.mapped != MagickFalse)
05898 (void) XWithdrawWindow(display,windows->info.id,
05899 windows->info.screen);
05900 break;
05901 }
05902 case RectangleElement:
05903 case FillRectangleElement:
05904 {
05905 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
05906 {
05907
05908
05909
05910 (void) FormatMagickString(text,MaxTextExtent," %lux%lu%+ld%+ld",
05911 rectangle_info.width,rectangle_info.height,rectangle_info.x,
05912 rectangle_info.y);
05913 XInfoWidget(display,windows,text);
05914 XHighlightRectangle(display,windows->image.id,
05915 windows->image.highlight_context,&rectangle_info);
05916 }
05917 else
05918 if (windows->info.mapped != MagickFalse)
05919 (void) XWithdrawWindow(display,windows->info.id,
05920 windows->info.screen);
05921 break;
05922 }
05923 case CircleElement:
05924 case FillCircleElement:
05925 case EllipseElement:
05926 case FillEllipseElement:
05927 {
05928 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
05929 {
05930
05931
05932
05933 (void) FormatMagickString(text,MaxTextExtent," %lux%lu%+ld%+ld",
05934 rectangle_info.width,rectangle_info.height,rectangle_info.x,
05935 rectangle_info.y);
05936 XInfoWidget(display,windows,text);
05937 XHighlightEllipse(display,windows->image.id,
05938 windows->image.highlight_context,&rectangle_info);
05939 }
05940 else
05941 if (windows->info.mapped != MagickFalse)
05942 (void) XWithdrawWindow(display,windows->info.id,
05943 windows->info.screen);
05944 break;
05945 }
05946 case PolygonElement:
05947 case FillPolygonElement:
05948 {
05949 if (number_coordinates > 1)
05950 (void) XDrawLines(display,windows->image.id,
05951 windows->image.highlight_context,coordinate_info,
05952 number_coordinates,CoordModeOrigin);
05953 if (distance > 9)
05954 {
05955
05956
05957
05958 degrees=RadiansToDegrees(-atan2((double) (line_info.y2-
05959 line_info.y1),(double) (line_info.x2-line_info.x1)));
05960 (void) FormatMagickString(text,MaxTextExtent," %g",
05961 (double) degrees);
05962 XInfoWidget(display,windows,text);
05963 XHighlightLine(display,windows->image.id,
05964 windows->image.highlight_context,&line_info);
05965 }
05966 else
05967 if (windows->info.mapped != MagickFalse)
05968 (void) XWithdrawWindow(display,windows->info.id,
05969 windows->info.screen);
05970 break;
05971 }
05972 }
05973
05974
05975
05976 XScreenEvent(display,windows,&event);
05977 switch (element)
05978 {
05979 case PointElement:
05980 default:
05981 {
05982 if (number_coordinates > 1)
05983 (void) XDrawLines(display,windows->image.id,
05984 windows->image.highlight_context,coordinate_info,
05985 number_coordinates,CoordModeOrigin);
05986 break;
05987 }
05988 case LineElement:
05989 {
05990 if (distance > 9)
05991 XHighlightLine(display,windows->image.id,
05992 windows->image.highlight_context,&line_info);
05993 break;
05994 }
05995 case RectangleElement:
05996 case FillRectangleElement:
05997 {
05998 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
05999 XHighlightRectangle(display,windows->image.id,
06000 windows->image.highlight_context,&rectangle_info);
06001 break;
06002 }
06003 case CircleElement:
06004 case FillCircleElement:
06005 case EllipseElement:
06006 case FillEllipseElement:
06007 {
06008 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
06009 XHighlightEllipse(display,windows->image.id,
06010 windows->image.highlight_context,&rectangle_info);
06011 break;
06012 }
06013 case PolygonElement:
06014 case FillPolygonElement:
06015 {
06016 if (number_coordinates > 1)
06017 (void) XDrawLines(display,windows->image.id,
06018 windows->image.highlight_context,coordinate_info,
06019 number_coordinates,CoordModeOrigin);
06020 if (distance > 9)
06021 XHighlightLine(display,windows->image.id,
06022 windows->image.highlight_context,&line_info);
06023 break;
06024 }
06025 }
06026 switch (event.type)
06027 {
06028 case ButtonPress:
06029 break;
06030 case ButtonRelease:
06031 {
06032
06033
06034
06035 line_info.x2=event.xbutton.x;
06036 line_info.y2=event.xbutton.y;
06037 rectangle_info.x=event.xbutton.x;
06038 rectangle_info.y=event.xbutton.y;
06039 coordinate_info[number_coordinates].x=event.xbutton.x;
06040 coordinate_info[number_coordinates].y=event.xbutton.y;
06041 if (((element != PolygonElement) &&
06042 (element != FillPolygonElement)) || (distance <= 9))
06043 {
06044 state|=ExitState;
06045 break;
06046 }
06047 number_coordinates++;
06048 if (number_coordinates < (int) max_coordinates)
06049 {
06050 line_info.x1=event.xbutton.x;
06051 line_info.y1=event.xbutton.y;
06052 break;
06053 }
06054 max_coordinates<<=1;
06055 coordinate_info=(XPoint *) ResizeQuantumMemory(coordinate_info,
06056 max_coordinates,sizeof(*coordinate_info));
06057 if (coordinate_info == (XPoint *) NULL)
06058 (void) ThrowMagickException(&(*image)->exception,GetMagickModule(),
06059 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
06060 break;
06061 }
06062 case Expose:
06063 break;
06064 case MotionNotify:
06065 {
06066 if (event.xmotion.window != windows->image.id)
06067 break;
06068 if (element != PointElement)
06069 {
06070 line_info.x2=event.xmotion.x;
06071 line_info.y2=event.xmotion.y;
06072 rectangle_info.x=event.xmotion.x;
06073 rectangle_info.y=event.xmotion.y;
06074 break;
06075 }
06076 coordinate_info[number_coordinates].x=event.xbutton.x;
06077 coordinate_info[number_coordinates].y=event.xbutton.y;
06078 number_coordinates++;
06079 if (number_coordinates < (int) max_coordinates)
06080 break;
06081 max_coordinates<<=1;
06082 coordinate_info=(XPoint *) ResizeQuantumMemory(coordinate_info,
06083 max_coordinates,sizeof(*coordinate_info));
06084 if (coordinate_info == (XPoint *) NULL)
06085 (void) ThrowMagickException(&(*image)->exception,GetMagickModule(),
06086 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
06087 break;
06088 }
06089 default:
06090 break;
06091 }
06092
06093
06094
06095 if (line_info.x2 < 0)
06096 line_info.x2=0;
06097 else
06098 if (line_info.x2 > (int) windows->image.width)
06099 line_info.x2=(short) windows->image.width;
06100 if (line_info.y2 < 0)
06101 line_info.y2=0;
06102 else
06103 if (line_info.y2 > (int) windows->image.height)
06104 line_info.y2=(short) windows->image.height;
06105 distance=(unsigned int)
06106 (((line_info.x2-line_info.x1+1)*(line_info.x2-line_info.x1+1))+
06107 ((line_info.y2-line_info.y1+1)*(line_info.y2-line_info.y1+1)));
06108 if ((((int) rectangle_info.x != x) && ((int) rectangle_info.y != y)) ||
06109 ((state & ExitState) != 0))
06110 {
06111 if (rectangle_info.x < 0)
06112 rectangle_info.x=0;
06113 else
06114 if (rectangle_info.x > (int) windows->image.width)
06115 rectangle_info.x=(long) windows->image.width;
06116 if ((int) rectangle_info.x < x)
06117 rectangle_info.width=(unsigned int) (x-rectangle_info.x);
06118 else
06119 {
06120 rectangle_info.width=(unsigned int) (rectangle_info.x-x);
06121 rectangle_info.x=x;
06122 }
06123 if (rectangle_info.y < 0)
06124 rectangle_info.y=0;
06125 else
06126 if (rectangle_info.y > (int) windows->image.height)
06127 rectangle_info.y=(long) windows->image.height;
06128 if ((int) rectangle_info.y < y)
06129 rectangle_info.height=(unsigned int) (y-rectangle_info.y);
06130 else
06131 {
06132 rectangle_info.height=(unsigned int) (rectangle_info.y-y);
06133 rectangle_info.y=y;
06134 }
06135 }
06136 } while ((state & ExitState) == 0);
06137 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
06138 if ((element == PointElement) || (element == PolygonElement) ||
06139 (element == FillPolygonElement))
06140 {
06141
06142
06143
06144 rectangle_info.x=coordinate_info->x;
06145 rectangle_info.y=coordinate_info->y;
06146 x=coordinate_info->x;
06147 y=coordinate_info->y;
06148 for (i=1; i < number_coordinates; i++)
06149 {
06150 if (coordinate_info[i].x > x)
06151 x=coordinate_info[i].x;
06152 if (coordinate_info[i].y > y)
06153 y=coordinate_info[i].y;
06154 if (coordinate_info[i].x < rectangle_info.x)
06155 rectangle_info.x=MagickMax(coordinate_info[i].x,0);
06156 if (coordinate_info[i].y < rectangle_info.y)
06157 rectangle_info.y=MagickMax(coordinate_info[i].y,0);
06158 }
06159 rectangle_info.width=(unsigned long) (x-rectangle_info.x);
06160 rectangle_info.height=(unsigned long) (y-rectangle_info.y);
06161 for (i=0; i < number_coordinates; i++)
06162 {
06163 coordinate_info[i].x-=rectangle_info.x;
06164 coordinate_info[i].y-=rectangle_info.y;
06165 }
06166 }
06167 else
06168 if (distance <= 9)
06169 continue;
06170 else
06171 if ((element == RectangleElement) ||
06172 (element == CircleElement) || (element == EllipseElement))
06173 {
06174 rectangle_info.width--;
06175 rectangle_info.height--;
06176 }
06177
06178
06179
06180 draw_info.x=(int) rectangle_info.x;
06181 draw_info.y=(int) rectangle_info.y;
06182 (void) XMagickCommand(display,resource_info,windows,SaveToUndoBufferCommand,
06183 image);
06184 width=(unsigned int) (*image)->columns;
06185 height=(unsigned int) (*image)->rows;
06186 x=0;
06187 y=0;
06188 if (windows->image.crop_geometry != (char *) NULL)
06189 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
06190 draw_info.x+=windows->image.x-(line_width/2);
06191 if (draw_info.x < 0)
06192 draw_info.x=0;
06193 draw_info.x=(int) (width*draw_info.x/windows->image.ximage->width);
06194 draw_info.y+=windows->image.y-(line_width/2);
06195 if (draw_info.y < 0)
06196 draw_info.y=0;
06197 draw_info.y=(int) height*draw_info.y/windows->image.ximage->height;
06198 draw_info.width=(unsigned int) rectangle_info.width+(line_width << 1);
06199 if (draw_info.width > (unsigned int) (*image)->columns)
06200 draw_info.width=(unsigned int) (*image)->columns;
06201 draw_info.height=(unsigned int) rectangle_info.height+(line_width << 1);
06202 if (draw_info.height > (unsigned int) (*image)->rows)
06203 draw_info.height=(unsigned int) (*image)->rows;
06204 (void) FormatMagickString(draw_info.geometry,MaxTextExtent,"%ux%u%+d%+d",
06205 width*draw_info.width/windows->image.ximage->width,
06206 height*draw_info.height/windows->image.ximage->height,
06207 draw_info.x+x,draw_info.y+y);
06208
06209
06210
06211 draw_info.degrees=0.0;
06212 draw_info.element=element;
06213 draw_info.stipple=stipple;
06214 draw_info.line_width=line_width;
06215 draw_info.line_info=line_info;
06216 if (line_info.x1 > (int) (line_width/2))
06217 draw_info.line_info.x1=(short) line_width/2;
06218 if (line_info.y1 > (int) (line_width/2))
06219 draw_info.line_info.y1=(short) line_width/2;
06220 draw_info.line_info.x2=(short) (line_info.x2-line_info.x1+(line_width/2));
06221 draw_info.line_info.y2=(short) (line_info.y2-line_info.y1+(line_width/2));
06222 if ((draw_info.line_info.x2 < 0) && (draw_info.line_info.y2 < 0))
06223 {
06224 draw_info.line_info.x2=(-draw_info.line_info.x2);
06225 draw_info.line_info.y2=(-draw_info.line_info.y2);
06226 }
06227 if (draw_info.line_info.x2 < 0)
06228 {
06229 draw_info.line_info.x2=(-draw_info.line_info.x2);
06230 Swap(draw_info.line_info.x1,draw_info.line_info.x2);
06231 }
06232 if (draw_info.line_info.y2 < 0)
06233 {
06234 draw_info.line_info.y2=(-draw_info.line_info.y2);
06235 Swap(draw_info.line_info.y1,draw_info.line_info.y2);
06236 }
06237 draw_info.rectangle_info=rectangle_info;
06238 if (draw_info.rectangle_info.x > (int) (line_width/2))
06239 draw_info.rectangle_info.x=(long) line_width/2;
06240 if (draw_info.rectangle_info.y > (int) (line_width/2))
06241 draw_info.rectangle_info.y=(long) line_width/2;
06242 draw_info.number_coordinates=(unsigned int) number_coordinates;
06243 draw_info.coordinate_info=coordinate_info;
06244 windows->pixel_info->pen_color=windows->pixel_info->pen_colors[pen_id];
06245
06246
06247
06248 XSetCursorState(display,windows,MagickTrue);
06249 XCheckRefreshWindows(display,windows);
06250 status=XDrawImage(display,windows->pixel_info,&draw_info,*image);
06251 XSetCursorState(display,windows,MagickFalse);
06252
06253
06254
06255 XConfigureImageColormap(display,resource_info,windows,*image);
06256 (void) XConfigureImage(display,resource_info,windows,*image);
06257 }
06258 XSetCursorState(display,windows,MagickFalse);
06259 coordinate_info=(XPoint *) RelinquishMagickMemory(coordinate_info);
06260 return(status != 0 ? MagickTrue : MagickFalse);
06261 }
06262
06263
06264
06265
06266
06267
06268
06269
06270
06271
06272
06273
06274
06275
06276
06277
06278
06279
06280
06281
06282
06283
06284
06285
06286
06287
06288
06289
06290 static void XDrawPanRectangle(Display *display,XWindows *windows)
06291 {
06292 MagickRealType
06293 scale_factor;
06294
06295 RectangleInfo
06296 highlight_info;
06297
06298
06299
06300
06301 scale_factor=(MagickRealType) windows->pan.width/windows->image.ximage->width;
06302 highlight_info.x=(int) (scale_factor*windows->image.x+0.5);
06303 highlight_info.width=(unsigned int) (scale_factor*windows->image.width+0.5);
06304 scale_factor=(MagickRealType)
06305 windows->pan.height/windows->image.ximage->height;
06306 highlight_info.y=(int) (scale_factor*windows->image.y+0.5);
06307 highlight_info.height=(unsigned int) (scale_factor*windows->image.height+0.5);
06308
06309
06310
06311 (void) XClearWindow(display,windows->pan.id);
06312 XHighlightRectangle(display,windows->pan.id,windows->pan.annotate_context,
06313 &highlight_info);
06314 }
06315
06316
06317
06318
06319
06320
06321
06322
06323
06324
06325
06326
06327
06328
06329
06330
06331
06332
06333
06334
06335
06336
06337
06338
06339
06340
06341
06342
06343
06344
06345
06346
06347
06348
06349
06350 static void XImageCache(Display *display,XResourceInfo *resource_info,
06351 XWindows *windows,const CommandType command,Image **image)
06352 {
06353 Image
06354 *cache_image;
06355
06356 static Image
06357 *redo_image = (Image *) NULL,
06358 *undo_image = (Image *) NULL;
06359
06360 switch (command)
06361 {
06362 case FreeBuffersCommand:
06363 {
06364
06365
06366
06367 while (undo_image != (Image *) NULL)
06368 {
06369 cache_image=undo_image;
06370 undo_image=GetPreviousImageInList(undo_image);
06371 cache_image->list=DestroyImage(cache_image->list);
06372 cache_image=DestroyImage(cache_image);
06373 }
06374 undo_image=NewImageList();
06375 if (redo_image != (Image *) NULL)
06376 redo_image=DestroyImage(redo_image);
06377 redo_image=NewImageList();
06378 return;
06379 }
06380 case UndoCommand:
06381 {
06382
06383
06384
06385 if (undo_image == (Image *) NULL)
06386 {
06387 (void) XBell(display,0);
06388 return;
06389 }
06390 cache_image=undo_image;
06391 undo_image=GetPreviousImageInList(undo_image);
06392 windows->image.window_changes.width=(int) cache_image->columns;
06393 windows->image.window_changes.height=(int) cache_image->rows;
06394 if (windows->image.crop_geometry != (char *) NULL)
06395 windows->image.crop_geometry=(char *)
06396 RelinquishMagickMemory(windows->image.crop_geometry);
06397 windows->image.crop_geometry=cache_image->geometry;
06398 if (redo_image != (Image *) NULL)
06399 redo_image=DestroyImage(redo_image);
06400 redo_image=(*image);
06401 *image=cache_image->list;
06402 cache_image=DestroyImage(cache_image);
06403 if (windows->image.orphan != MagickFalse)
06404 return;
06405 XConfigureImageColormap(display,resource_info,windows,*image);
06406 (void) XConfigureImage(display,resource_info,windows,*image);
06407 return;
06408 }
06409 case CutCommand:
06410 case PasteCommand:
06411 case ApplyCommand:
06412 case HalfSizeCommand:
06413 case OriginalSizeCommand:
06414 case DoubleSizeCommand:
06415 case ResizeCommand:
06416 case TrimCommand:
06417 case CropCommand:
06418 case ChopCommand:
06419 case FlipCommand:
06420 case FlopCommand:
06421 case RotateRightCommand:
06422 case RotateLeftCommand:
06423 case RotateCommand:
06424 case ShearCommand:
06425 case RollCommand:
06426 case NegateCommand:
06427 case ContrastStretchCommand:
06428 case SigmoidalContrastCommand:
06429 case NormalizeCommand:
06430 case EqualizeCommand:
06431 case HueCommand:
06432 case SaturationCommand:
06433 case BrightnessCommand:
06434 case GammaCommand:
06435 case SpiffCommand:
06436 case DullCommand:
06437 case GrayscaleCommand:
06438 case MapCommand:
06439 case QuantizeCommand:
06440 case DespeckleCommand:
06441 case EmbossCommand:
06442 case ReduceNoiseCommand:
06443 case AddNoiseCommand:
06444 case SharpenCommand:
06445 case BlurCommand:
06446 case ThresholdCommand:
06447 case EdgeDetectCommand:
06448 case SpreadCommand:
06449 case ShadeCommand:
06450 case RaiseCommand:
06451 case SegmentCommand:
06452 case SolarizeCommand:
06453 case SepiaToneCommand:
06454 case SwirlCommand:
06455 case ImplodeCommand:
06456 case VignetteCommand:
06457 case WaveCommand:
06458 case OilPaintCommand:
06459 case CharcoalDrawCommand:
06460 case AnnotateCommand:
06461 case AddBorderCommand:
06462 case AddFrameCommand:
06463 case CompositeCommand:
06464 case CommentCommand:
06465 case LaunchCommand:
06466 case RegionofInterestCommand:
06467 case SaveToUndoBufferCommand:
06468 case RedoCommand:
06469 {
06470 Image
06471 *previous_image;
06472
06473 long
06474 bytes;
06475
06476 bytes=(long) ((*image)->columns*(*image)->rows*sizeof(PixelPacket));
06477 if (undo_image != (Image *) NULL)
06478 {
06479
06480
06481
06482 previous_image=undo_image;
06483 while (previous_image != (Image *) NULL)
06484 {
06485 bytes+=previous_image->list->columns*previous_image->list->rows*
06486 sizeof(PixelPacket);
06487 if (bytes <= (long) (resource_info->undo_cache << 20))
06488 {
06489 previous_image=GetPreviousImageInList(previous_image);
06490 continue;
06491 }
06492 bytes-=previous_image->list->columns*previous_image->list->rows*
06493 sizeof(PixelPacket);
06494 if (previous_image == undo_image)
06495 undo_image=NewImageList();
06496 else
06497 previous_image->next->previous=NewImageList();
06498 break;
06499 }
06500 while (previous_image != (Image *) NULL)
06501 {
06502
06503
06504
06505 cache_image=previous_image;
06506 previous_image=GetPreviousImageInList(previous_image);
06507 cache_image->list=DestroyImage(cache_image->list);
06508 cache_image=DestroyImage(cache_image);
06509 }
06510 }
06511 if (bytes > (long) (resource_info->undo_cache << 20))
06512 break;
06513
06514
06515
06516 cache_image=AcquireImage((ImageInfo *) NULL);
06517 if (cache_image == (Image *) NULL)
06518 break;
06519 XSetCursorState(display,windows,MagickTrue);
06520 XCheckRefreshWindows(display,windows);
06521 cache_image->list=CloneImage(*image,0,0,MagickTrue,&(*image)->exception);
06522 XSetCursorState(display,windows,MagickFalse);
06523 if (cache_image->list == (Image *) NULL)
06524 {
06525 cache_image=DestroyImage(cache_image);
06526 break;
06527 }
06528 cache_image->columns=(unsigned long) windows->image.ximage->width;
06529 cache_image->rows=(unsigned long) windows->image.ximage->height;
06530 cache_image->geometry=windows->image.crop_geometry;
06531 if (windows->image.crop_geometry != (char *) NULL)
06532 {
06533 cache_image->geometry=AcquireString((char *) NULL);
06534 (void) CopyMagickString(cache_image->geometry,
06535 windows->image.crop_geometry,MaxTextExtent);
06536 }
06537 if (undo_image == (Image *) NULL)
06538 {
06539 undo_image=cache_image;
06540 break;
06541 }
06542 undo_image->next=cache_image;
06543 undo_image->next->previous=undo_image;
06544 undo_image=undo_image->next;
06545 break;
06546 }
06547 default:
06548 break;
06549 }
06550 if (command == RedoCommand)
06551 {
06552
06553
06554
06555 if (redo_image == (Image *) NULL)
06556 {
06557 (void) XBell(display,0);
06558 return;
06559 }
06560 windows->image.window_changes.width=(int) redo_image->columns;
06561 windows->image.window_changes.height=(int) redo_image->rows;
06562 if (windows->image.crop_geometry != (char *) NULL)
06563 windows->image.crop_geometry=(char *)
06564 RelinquishMagickMemory(windows->image.crop_geometry);
06565 windows->image.crop_geometry=redo_image->geometry;
06566 *image=DestroyImage(*image);
06567 *image=redo_image;
06568 redo_image=NewImageList();
06569 if (windows->image.orphan != MagickFalse)
06570 return;
06571 XConfigureImageColormap(display,resource_info,windows,*image);
06572 (void) XConfigureImage(display,resource_info,windows,*image);
06573 return;
06574 }
06575 if (command != InfoCommand)
06576 return;
06577
06578
06579
06580 XSetCursorState(display,windows,MagickTrue);
06581 XCheckRefreshWindows(display,windows);
06582 XDisplayImageInfo(display,resource_info,windows,undo_image,*image);
06583 XSetCursorState(display,windows,MagickFalse);
06584 }
06585
06586
06587
06588
06589
06590
06591
06592
06593
06594
06595
06596
06597
06598
06599
06600
06601
06602
06603
06604
06605
06606
06607
06608
06609
06610
06611
06612
06613
06614
06615
06616
06617
06618
06619
06620
06621
06622
06623
06624
06625
06626
06627 static CommandType XImageWindowCommand(Display *display,
06628 XResourceInfo *resource_info,XWindows *windows,const MagickStatusType state,
06629 KeySym key_symbol,Image **image)
06630 {
06631 static char
06632 delta[MaxTextExtent] = "";
06633
06634 static const char
06635 Digits[] = "01234567890";
06636
06637 static KeySym
06638 last_symbol = XK_0;
06639
06640 if ((key_symbol >= XK_0) && (key_symbol <= XK_9))
06641 {
06642 if (((last_symbol < XK_0) || (last_symbol > XK_9)))
06643 {
06644 *delta='\0';
06645 resource_info->quantum=1;
06646 }
06647 last_symbol=key_symbol;
06648 delta[strlen(delta)+1]='\0';
06649 delta[strlen(delta)]=Digits[key_symbol-XK_0];
06650 resource_info->quantum=atoi(delta);
06651 return(NullCommand);
06652 }
06653 last_symbol=key_symbol;
06654 if (resource_info->immutable)
06655 {
06656
06657
06658
06659 switch (key_symbol)
06660 {
06661 case XK_question:
06662 return(InfoCommand);
06663 case XK_p:
06664 case XK_Print:
06665 return(PrintCommand);
06666 case XK_space:
06667 return(NextCommand);
06668 case XK_q:
06669 case XK_Escape:
06670 return(QuitCommand);
06671 default:
06672 break;
06673 }
06674 return(NullCommand);
06675 }
06676 switch ((int) key_symbol)
06677 {
06678 case XK_o:
06679 {
06680 if ((state & ControlMask) == 0)
06681 break;
06682 return(OpenCommand);
06683 }
06684 case XK_space:
06685 return(NextCommand);
06686 case XK_BackSpace:
06687 return(FormerCommand);
06688 case XK_s:
06689 {
06690 if ((state & Mod1Mask) != 0)
06691 return(SwirlCommand);
06692 if ((state & ControlMask) == 0)
06693 return(ShearCommand);
06694 return(SaveCommand);
06695 }
06696 case XK_p:
06697 case XK_Print:
06698 {
06699 if ((state & Mod1Mask) != 0)
06700 return(OilPaintCommand);
06701 if ((state & Mod4Mask) != 0)
06702 return(ColorCommand);
06703 if ((state & ControlMask) == 0)
06704 return(NullCommand);
06705 return(PrintCommand);
06706 }
06707 case XK_d:
06708 {
06709 if ((state & Mod4Mask) != 0)
06710 return(DrawCommand);
06711 if ((state & ControlMask) == 0)
06712 return(NullCommand);
06713 return(DeleteCommand);
06714 }
06715 case XK_Select:
06716 {
06717 if ((state & ControlMask) == 0)
06718 return(NullCommand);
06719 return(SelectCommand);
06720 }
06721 case XK_n:
06722 {
06723 if ((state & ControlMask) == 0)
06724 return(NullCommand);
06725 return(NewCommand);
06726 }
06727 case XK_q:
06728 case XK_Escape:
06729 return(QuitCommand);
06730 case XK_z:
06731 case XK_Undo:
06732 {
06733 if ((state & ControlMask) == 0)
06734 return(NullCommand);
06735 return(UndoCommand);
06736 }
06737 case XK_r:
06738 case XK_Redo:
06739 {
06740 if ((state & ControlMask) == 0)
06741 return(RollCommand);
06742 return(RedoCommand);
06743 }
06744 case XK_x:
06745 {
06746 if ((state & ControlMask) == 0)
06747 return(NullCommand);
06748 return(CutCommand);
06749 }
06750 case XK_c:
06751 {
06752 if ((state & Mod1Mask) != 0)
06753 return(CharcoalDrawCommand);
06754 if ((state & ControlMask) == 0)
06755 return(CropCommand);
06756 return(CopyCommand);
06757 }
06758 case XK_v:
06759 case XK_Insert:
06760 {
06761 if ((state & Mod4Mask) != 0)
06762 return(CompositeCommand);
06763 if ((state & ControlMask) == 0)
06764 return(FlipCommand);
06765 return(PasteCommand);
06766 }
06767 case XK_less:
06768 return(HalfSizeCommand);
06769 case XK_minus:
06770 return(OriginalSizeCommand);
06771 case XK_greater:
06772 return(DoubleSizeCommand);
06773 case XK_percent:
06774 return(ResizeCommand);
06775 case XK_at:
06776 return(RefreshCommand);
06777 case XK_bracketleft:
06778 return(ChopCommand);
06779 case XK_h:
06780 return(FlopCommand);
06781 case XK_slash:
06782 return(RotateRightCommand);
06783 case XK_backslash:
06784 return(RotateLeftCommand);
06785 case XK_asterisk:
06786 return(RotateCommand);
06787 case XK_t:
06788 return(TrimCommand);
06789 case XK_H:
06790 return(HueCommand);
06791 case XK_S:
06792 return(SaturationCommand);
06793 case XK_L:
06794 return(BrightnessCommand);
06795 case XK_G:
06796 return(GammaCommand);
06797 case XK_C:
06798 return(SpiffCommand);
06799 case XK_Z:
06800 return(DullCommand);
06801 case XK_N:
06802 return(NormalizeCommand);
06803 case XK_equal:
06804 return(EqualizeCommand);
06805 case XK_asciitilde:
06806 return(NegateCommand);
06807 case XK_period:
06808 return(GrayscaleCommand);
06809 case XK_numbersign:
06810 return(QuantizeCommand);
06811 case XK_F2:
06812 return(DespeckleCommand);
06813 case XK_F3:
06814 return(EmbossCommand);
06815 case XK_F4:
06816 return(ReduceNoiseCommand);
06817 case XK_F5:
06818 return(AddNoiseCommand);
06819 case XK_F6:
06820 return(SharpenCommand);
06821 case XK_F7:
06822 return(BlurCommand);
06823 case XK_F8:
06824 return(ThresholdCommand);
06825 case XK_F9:
06826 return(EdgeDetectCommand);
06827 case XK_F10:
06828 return(SpreadCommand);
06829 case XK_F11:
06830 return(ShadeCommand);
06831 case XK_F12:
06832 return(RaiseCommand);
06833 case XK_F13:
06834 return(SegmentCommand);
06835 case XK_i:
06836 {
06837 if ((state & Mod1Mask) == 0)
06838 return(NullCommand);
06839 return(ImplodeCommand);
06840 }
06841 case XK_w:
06842 {
06843 if ((state & Mod1Mask) == 0)
06844 return(NullCommand);
06845 return(WaveCommand);
06846 }
06847 case XK_m:
06848 {
06849 if ((state & Mod4Mask) == 0)
06850 return(NullCommand);
06851 return(MatteCommand);
06852 }
06853 case XK_b:
06854 {
06855 if ((state & Mod4Mask) == 0)
06856 return(NullCommand);
06857 return(AddBorderCommand);
06858 }
06859 case XK_f:
06860 {
06861 if ((state & Mod4Mask) == 0)
06862 return(NullCommand);
06863 return(AddFrameCommand);
06864 }
06865 case XK_exclam:
06866 {
06867 if ((state & Mod4Mask) == 0)
06868 return(NullCommand);
06869 return(CommentCommand);
06870 }
06871 case XK_a:
06872 {
06873 if ((state & Mod1Mask) != 0)
06874 return(ApplyCommand);
06875 if ((state & Mod4Mask) != 0)
06876 return(AnnotateCommand);
06877 if ((state & ControlMask) == 0)
06878 return(NullCommand);
06879 return(RegionofInterestCommand);
06880 }
06881 case XK_question:
06882 return(InfoCommand);
06883 case XK_plus:
06884 return(ZoomCommand);
06885 case XK_P:
06886 {
06887 if ((state & ShiftMask) == 0)
06888 return(NullCommand);
06889 return(ShowPreviewCommand);
06890 }
06891 case XK_Execute:
06892 return(LaunchCommand);
06893 case XK_F1:
06894 return(HelpCommand);
06895 case XK_Find:
06896 return(BrowseDocumentationCommand);
06897 case XK_Menu:
06898 {
06899 (void) XMapRaised(display,windows->command.id);
06900 return(NullCommand);
06901 }
06902 case XK_Next:
06903 case XK_Prior:
06904 case XK_Home:
06905 case XK_KP_Home:
06906 {
06907 XTranslateImage(display,windows,*image,key_symbol);
06908 return(NullCommand);
06909 }
06910 case XK_Up:
06911 case XK_KP_Up:
06912 case XK_Down:
06913 case XK_KP_Down:
06914 case XK_Left:
06915 case XK_KP_Left:
06916 case XK_Right:
06917 case XK_KP_Right:
06918 {
06919 if ((state & Mod1Mask) != 0)
06920 {
06921 RectangleInfo
06922 crop_info;
06923
06924
06925
06926
06927 crop_info.x=0;
06928 crop_info.y=0;
06929 crop_info.width=(unsigned long) windows->image.ximage->width;
06930 crop_info.height=(unsigned long) windows->image.ximage->height;
06931 if ((key_symbol == XK_Up) || (key_symbol == XK_KP_Up))
06932 {
06933 if (resource_info->quantum >= (int) crop_info.height)
06934 resource_info->quantum=(int) crop_info.height-1;
06935 crop_info.height-=resource_info->quantum;
06936 }
06937 if ((key_symbol == XK_Down) || (key_symbol == XK_KP_Down))
06938 {
06939 if (resource_info->quantum >= (int) (crop_info.height-crop_info.y))
06940 resource_info->quantum=(int) (crop_info.height-crop_info.y-1);
06941 crop_info.y+=resource_info->quantum;
06942 crop_info.height-=resource_info->quantum;
06943 }
06944 if ((key_symbol == XK_Left) || (key_symbol == XK_KP_Left))
06945 {
06946 if (resource_info->quantum >= (int) crop_info.width)
06947 resource_info->quantum=(int) crop_info.width-1;
06948 crop_info.width-=resource_info->quantum;
06949 }
06950 if ((key_symbol == XK_Right) || (key_symbol == XK_KP_Right))
06951 {
06952 if (resource_info->quantum >= (int) (crop_info.width-crop_info.x))
06953 resource_info->quantum=(int) (crop_info.width-crop_info.x-1);
06954 crop_info.x+=resource_info->quantum;
06955 crop_info.width-=resource_info->quantum;
06956 }
06957 if ((int) (windows->image.x+windows->image.width) >
06958 (int) crop_info.width)
06959 windows->image.x=(int) (crop_info.width-windows->image.width);
06960 if ((int) (windows->image.y+windows->image.height) >
06961 (int) crop_info.height)
06962 windows->image.y=(int) (crop_info.height-windows->image.height);
06963 XSetCropGeometry(display,windows,&crop_info,*image);
06964 windows->image.window_changes.width=(int) crop_info.width;
06965 windows->image.window_changes.height=(int) crop_info.height;
06966 (void) XSetWindowBackgroundPixmap(display,windows->image.id,None);
06967 (void) XConfigureImage(display,resource_info,windows,*image);
06968 return(NullCommand);
06969 }
06970 XTranslateImage(display,windows,*image,key_symbol);
06971 return(NullCommand);
06972 }
06973 default:
06974 return(NullCommand);
06975 }
06976 return(NullCommand);
06977 }
06978
06979
06980
06981
06982
06983
06984
06985
06986
06987
06988
06989
06990
06991
06992
06993
06994
06995
06996
06997
06998
06999
07000
07001
07002
07003
07004
07005
07006
07007
07008
07009
07010
07011
07012
07013
07014
07015
07016
07017 static Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
07018 XWindows *windows,const CommandType command,Image **image)
07019 {
07020 char
07021 filename[MaxTextExtent],
07022 geometry[MaxTextExtent],
07023 modulate_factors[MaxTextExtent];
07024
07025 GeometryInfo
07026 geometry_info;
07027
07028 Image
07029 *nexus;
07030
07031 ImageInfo
07032 *image_info;
07033
07034 int
07035 x,
07036 y;
07037
07038 MagickStatusType
07039 flags,
07040 status;
07041
07042 QuantizeInfo
07043 quantize_info;
07044
07045 RectangleInfo
07046 page_geometry;
07047
07048 register int
07049 i;
07050
07051 static char
07052 color[MaxTextExtent] = "gray";
07053
07054 unsigned int
07055 height,
07056 width;
07057
07058
07059
07060
07061 XCheckRefreshWindows(display,windows);
07062 XImageCache(display,resource_info,windows,command,image);
07063 nexus=NewImageList();
07064 windows->image.window_changes.width=windows->image.ximage->width;
07065 windows->image.window_changes.height=windows->image.ximage->height;
07066 image_info=CloneImageInfo(resource_info->image_info);
07067 SetGeometryInfo(&geometry_info);
07068 GetQuantizeInfo(&quantize_info);
07069 switch (command)
07070 {
07071 case OpenCommand:
07072 {
07073
07074
07075
07076 nexus=XOpenImage(display,resource_info,windows,MagickFalse);
07077 break;
07078 }
07079 case NextCommand:
07080 {
07081
07082
07083
07084 for (i=0; i < resource_info->quantum; i++)
07085 XClientMessage(display,windows->image.id,windows->im_protocols,
07086 windows->im_next_image,CurrentTime);
07087 break;
07088 }
07089 case FormerCommand:
07090 {
07091
07092
07093
07094 for (i=0; i < resource_info->quantum; i++)
07095 XClientMessage(display,windows->image.id,windows->im_protocols,
07096 windows->im_former_image,CurrentTime);
07097 break;
07098 }
07099 case SelectCommand:
07100 {
07101 int
07102 status;
07103
07104
07105
07106
07107 status=chdir(resource_info->home_directory);
07108 if (status == -1)
07109 (void) ThrowMagickException(&(*image)->exception,GetMagickModule(),
07110 FileOpenError,"UnableToOpenFile","%s",resource_info->home_directory);
07111 nexus=XOpenImage(display,resource_info,windows,MagickTrue);
07112 break;
07113 }
07114 case SaveCommand:
07115 {
07116
07117
07118
07119 status=XSaveImage(display,resource_info,windows,*image);
07120 if (status == MagickFalse)
07121 {
07122 XNoticeWidget(display,windows,"Unable to write X image:",
07123 (*image)->filename);
07124 break;
07125 }
07126 break;
07127 }
07128 case PrintCommand:
07129 {
07130
07131
07132
07133 status=XPrintImage(display,resource_info,windows,*image);
07134 if (status == MagickFalse)
07135 {
07136 XNoticeWidget(display,windows,"Unable to print X image:",
07137 (*image)->filename);
07138 break;
07139 }
07140 break;
07141 }
07142 case DeleteCommand:
07143 {
07144 static char
07145 filename[MaxTextExtent] = "\0";
07146
07147
07148
07149
07150 XFileBrowserWidget(display,windows,"Delete",filename);
07151 if (*filename == '\0')
07152 break;
07153 status=remove(filename) != 0 ? MagickTrue : MagickFalse;
07154 if (status != MagickFalse)
07155 XNoticeWidget(display,windows,"Unable to delete image file:",filename);
07156 break;
07157 }
07158 case NewCommand:
07159 {
07160 int
07161 status;
07162
07163 static char
07164 color[MaxTextExtent] = "gray",
07165 geometry[MaxTextExtent] = "640x480";
07166
07167 static const char
07168 *format = "gradient";
07169
07170
07171
07172
07173 status=XDialogWidget(display,windows,"New","Enter image geometry:",
07174 geometry);
07175 if (*geometry == '\0')
07176 break;
07177 if (status == 0)
07178 format="xc";
07179 XColorBrowserWidget(display,windows,"Select",color);
07180 if (*color == '\0')
07181 break;
07182
07183
07184
07185 (void) FormatMagickString(image_info->filename,MaxTextExtent,
07186 "%s:%s",format,color);
07187 (void) CloneString(&image_info->size,geometry);
07188 nexus=ReadImage(image_info,&(*image)->exception);
07189 CatchException(&(*image)->exception);
07190 XClientMessage(display,windows->image.id,windows->im_protocols,
07191 windows->im_next_image,CurrentTime);
07192 break;
07193 }
07194 case VisualDirectoryCommand:
07195 {
07196
07197
07198
07199 nexus=XVisualDirectoryImage(display,resource_info,windows);
07200 break;
07201 }
07202 case QuitCommand:
07203 {
07204
07205
07206
07207 if (resource_info->confirm_exit == MagickFalse)
07208 XClientMessage(display,windows->image.id,windows->im_protocols,
07209 windows->im_exit,CurrentTime);
07210 else
07211 {
07212 int
07213 status;
07214
07215
07216
07217
07218 status=XConfirmWidget(display,windows,"Do you really want to exit",
07219 resource_info->client_name);
07220 if (status > 0)
07221 XClientMessage(display,windows->image.id,windows->im_protocols,
07222 windows->im_exit,CurrentTime);
07223 }
07224 break;
07225 }
07226 case CutCommand:
07227 {
07228
07229
07230
07231 (void) XCropImage(display,resource_info,windows,*image,CutMode);
07232 break;
07233 }
07234 case CopyCommand:
07235 {
07236
07237
07238
07239 (void) XCropImage(display,resource_info,windows,*image,CopyMode);
07240 break;
07241 }
07242 case PasteCommand:
07243 {
07244
07245
07246
07247 status=XPasteImage(display,resource_info,windows,*image);
07248 if (status == MagickFalse)
07249 {
07250 XNoticeWidget(display,windows,"Unable to paste X image",
07251 (*image)->filename);
07252 break;
07253 }
07254 break;
07255 }
07256 case HalfSizeCommand:
07257 {
07258
07259
07260
07261 windows->image.window_changes.width=windows->image.ximage->width/2;
07262 windows->image.window_changes.height=windows->image.ximage->height/2;
07263 (void) XConfigureImage(display,resource_info,windows,*image);
07264 break;
07265 }
07266 case OriginalSizeCommand:
07267 {
07268
07269
07270
07271 windows->image.window_changes.width=(int) (*image)->columns;
07272 windows->image.window_changes.height=(int) (*image)->rows;
07273 (void) XConfigureImage(display,resource_info,windows,*image);
07274 break;
07275 }
07276 case DoubleSizeCommand:
07277 {
07278
07279
07280
07281 windows->image.window_changes.width=windows->image.ximage->width << 1;
07282 windows->image.window_changes.height=windows->image.ximage->height << 1;
07283 (void) XConfigureImage(display,resource_info,windows,*image);
07284 break;
07285 }
07286 case ResizeCommand:
07287 {
07288 int
07289 status;
07290
07291 long
07292 x,
07293 y;
07294
07295 unsigned long
07296 height,
07297 width;
07298
07299
07300
07301
07302 width=(unsigned long) windows->image.ximage->width;
07303 height=(unsigned long) windows->image.ximage->height;
07304 x=0;
07305 y=0;
07306 (void) FormatMagickString(geometry,MaxTextExtent,"%lux%lu+0+0",
07307 width,height);
07308 status=XDialogWidget(display,windows,"Resize",
07309 "Enter resize geometry (e.g. 640x480, 200%):",geometry);
07310 if (*geometry == '\0')
07311 break;
07312 if (status == 0)
07313 (void) ConcatenateMagickString(geometry,"!",MaxTextExtent);
07314 (void) ParseMetaGeometry(geometry,&x,&y,&width,&height);
07315 windows->image.window_changes.width=(int) width;
07316 windows->image.window_changes.height=(int) height;
07317 (void) XConfigureImage(display,resource_info,windows,*image);
07318 break;
07319 }
07320 case ApplyCommand:
07321 {
07322 char
07323 image_geometry[MaxTextExtent];
07324
07325 if ((windows->image.crop_geometry == (char *) NULL) &&
07326 ((int) (*image)->columns == windows->image.ximage->width) &&
07327 ((int) (*image)->rows == windows->image.ximage->height))
07328 break;
07329
07330
07331
07332 XSetCursorState(display,windows,MagickTrue);
07333 XCheckRefreshWindows(display,windows);
07334
07335
07336
07337 (void) FormatMagickString(image_geometry,MaxTextExtent,"%dx%d!",
07338 windows->image.ximage->width,windows->image.ximage->height);
07339 (void) TransformImage(image,windows->image.crop_geometry,image_geometry);
07340 if (windows->image.crop_geometry != (char *) NULL)
07341 windows->image.crop_geometry=(char *)
07342 RelinquishMagickMemory(windows->image.crop_geometry);
07343 windows->image.x=0;
07344 windows->image.y=0;
07345 XConfigureImageColormap(display,resource_info,windows,*image);
07346 (void) XConfigureImage(display,resource_info,windows,*image);
07347 break;
07348 }
07349 case RefreshCommand:
07350 {
07351 (void) XConfigureImage(display,resource_info,windows,*image);
07352 break;
07353 }
07354 case RestoreCommand:
07355 {
07356
07357
07358
07359 if ((windows->image.width == (unsigned int) (*image)->columns) &&
07360 (windows->image.height == (unsigned int) (*image)->rows) &&
07361 (windows->image.crop_geometry == (char *) NULL))
07362 {
07363 (void) XBell(display,0);
07364 break;
07365 }
07366 windows->image.window_changes.width=(int) (*image)->columns;
07367 windows->image.window_changes.height=(int) (*image)->rows;
07368 if (windows->image.crop_geometry != (char *) NULL)
07369 {
07370 windows->image.crop_geometry=(char *)
07371 RelinquishMagickMemory(windows->image.crop_geometry);
07372 windows->image.crop_geometry=(char *) NULL;
07373 windows->image.x=0;
07374 windows->image.y=0;
07375 }
07376 XConfigureImageColormap(display,resource_info,windows,*image);
07377 (void) XConfigureImage(display,resource_info,windows,*image);
07378 break;
07379 }
07380 case CropCommand:
07381 {
07382
07383
07384
07385 (void) XCropImage(display,resource_info,windows,*image,CropMode);
07386 break;
07387 }
07388 case ChopCommand:
07389 {
07390
07391
07392
07393 status=XChopImage(display,resource_info,windows,image);
07394 if (status == MagickFalse)
07395 {
07396 XNoticeWidget(display,windows,"Unable to cut X image",
07397 (*image)->filename);
07398 break;
07399 }
07400 break;
07401 }
07402 case FlopCommand:
07403 {
07404 Image
07405 *flop_image;
07406
07407
07408
07409
07410 XSetCursorState(display,windows,MagickTrue);
07411 XCheckRefreshWindows(display,windows);
07412 flop_image=FlopImage(*image,&(*image)->exception);
07413 if (flop_image != (Image *) NULL)
07414 {
07415 *image=DestroyImage(*image);
07416 *image=flop_image;
07417 }
07418 CatchException(&(*image)->exception);
07419 XSetCursorState(display,windows,MagickFalse);
07420 if (windows->image.crop_geometry != (char *) NULL)
07421 {
07422
07423
07424
07425 width=(unsigned int) (*image)->columns;
07426 height=(unsigned int) (*image)->rows;
07427 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
07428 &width,&height);
07429 (void) FormatMagickString(windows->image.crop_geometry,MaxTextExtent,
07430 "%ux%u%+d%+d",width,height,(int) (*image)->columns-(int) width-x,y);
07431 }
07432 if (windows->image.orphan != MagickFalse)
07433 break;
07434 (void) XConfigureImage(display,resource_info,windows,*image);
07435 break;
07436 }
07437 case FlipCommand:
07438 {
07439 Image
07440 *flip_image;
07441
07442
07443
07444
07445 XSetCursorState(display,windows,MagickTrue);
07446 XCheckRefreshWindows(display,windows);
07447 flip_image=FlipImage(*image,&(*image)->exception);
07448 if (flip_image != (Image *) NULL)
07449 {
07450 *image=DestroyImage(*image);
07451 *image=flip_image;
07452 }
07453 CatchException(&(*image)->exception);
07454 XSetCursorState(display,windows,MagickFalse);
07455 if (windows->image.crop_geometry != (char *) NULL)
07456 {
07457
07458
07459
07460 width=(unsigned int) (*image)->columns;
07461 height=(unsigned int) (*image)->rows;
07462 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
07463 &width,&height);
07464 (void) FormatMagickString(windows->image.crop_geometry,MaxTextExtent,
07465 "%ux%u%+d%+d",width,height,x,(int) (*image)->rows-(int) height-y);
07466 }
07467 if (windows->image.orphan != MagickFalse)
07468 break;
07469 (void) XConfigureImage(display,resource_info,windows,*image);
07470 break;
07471 }
07472 case RotateRightCommand:
07473 {
07474
07475
07476
07477 status=XRotateImage(display,resource_info,windows,90.0,image);
07478 if (status == MagickFalse)
07479 {
07480 XNoticeWidget(display,windows,"Unable to rotate X image",
07481 (*image)->filename);
07482 break;
07483 }
07484 break;
07485 }
07486 case RotateLeftCommand:
07487 {
07488
07489
07490
07491 status=XRotateImage(display,resource_info,windows,-90.0,image);
07492 if (status == MagickFalse)
07493 {
07494 XNoticeWidget(display,windows,"Unable to rotate X image",
07495 (*image)->filename);
07496 break;
07497 }
07498 break;
07499 }
07500 case RotateCommand:
07501 {
07502
07503
07504
07505 status=XRotateImage(display,resource_info,windows,0.0,image);
07506 if (status == MagickFalse)
07507 {
07508 XNoticeWidget(display,windows,"Unable to rotate X image",
07509 (*image)->filename);
07510 break;
07511 }
07512 break;
07513 }
07514 case ShearCommand:
07515 {
07516 Image
07517 *shear_image;
07518
07519 static char
07520 geometry[MaxTextExtent] = "45.0x45.0";
07521
07522
07523
07524
07525 XColorBrowserWidget(display,windows,"Select",color);
07526 if (*color == '\0')
07527 break;
07528 (void) XDialogWidget(display,windows,"Shear","Enter shear geometry:",
07529 geometry);
07530 if (*geometry == '\0')
07531 break;
07532
07533
07534
07535 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image);
07536 XSetCursorState(display,windows,MagickTrue);
07537 XCheckRefreshWindows(display,windows);
07538 (void) QueryColorDatabase(color,&(*image)->background_color,
07539 &(*image)->exception);
07540 flags=ParseGeometry(geometry,&geometry_info);
07541 if ((flags & SigmaValue) == 0)
07542 geometry_info.sigma=geometry_info.rho;
07543 shear_image=ShearImage(*image,geometry_info.rho,geometry_info.sigma,
07544 &(*image)->exception);
07545 if (shear_image != (Image *) NULL)
07546 {
07547 *image=DestroyImage(*image);
07548 *image=shear_image;
07549 }
07550 CatchException(&(*image)->exception);
07551 XSetCursorState(display,windows,MagickFalse);
07552 if (windows->image.orphan != MagickFalse)
07553 break;
07554 windows->image.window_changes.width=(int) (*image)->columns;
07555 windows->image.window_changes.height=(int) (*image)->rows;
07556 XConfigureImageColormap(display,resource_info,windows,*image);
07557 (void) XConfigureImage(display,resource_info,windows,*image);
07558 break;
07559 }
07560 case RollCommand:
07561 {
07562 Image
07563 *roll_image;
07564
07565 static char
07566 geometry[MaxTextExtent] = "+2+2";
07567
07568
07569
07570
07571 (void) XDialogWidget(display,windows,"Roll","Enter roll geometry:",
07572 geometry);
07573 if (*geometry == '\0')
07574 break;
07575
07576
07577
07578 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image);
07579 XSetCursorState(display,windows,MagickTrue);
07580 XCheckRefreshWindows(display,windows);
07581 (void) ParsePageGeometry(*image,geometry,&page_geometry,
07582 &(*image)->exception);
07583 roll_image=RollImage(*image,page_geometry.x,page_geometry.y,
07584 &(*image)->exception);
07585 if (roll_image != (Image *) NULL)
07586 {
07587 *image=DestroyImage(*image);
07588 *image=roll_image;
07589 }
07590 CatchException(&(*image)->exception);
07591 XSetCursorState(display,windows,MagickFalse);
07592 if (windows->image.orphan != MagickFalse)
07593 break;
07594 windows->image.window_changes.width=(int) (*image)->columns;
07595 windows->image.window_changes.height=(int) (*image)->rows;
07596 XConfigureImageColormap(display,resource_info,windows,*image);
07597 (void) XConfigureImage(display,resource_info,windows,*image);
07598 break;
07599 }
07600 case TrimCommand:
07601 {
07602 static char
07603 fuzz[MaxTextExtent];
07604
07605
07606
07607
07608 (void) FormatMagickString(fuzz,MaxTextExtent,"%g%%",100.0*(*image)->fuzz/
07609 (QuantumRange+1.0));
07610 (void) XDialogWidget(display,windows,"Trim","Enter fuzz factor:",fuzz);
07611 if (*fuzz == '\0')
07612 break;
07613 (*image)->fuzz=StringToDouble(fuzz,(double) QuantumRange+1.0);
07614
07615
07616
07617 status=XTrimImage(display,resource_info,windows,*image);
07618 if (status == MagickFalse)
07619 {
07620 XNoticeWidget(display,windows,"Unable to trim X image",
07621 (*image)->filename);
07622 break;
07623 }
07624 break;
07625 }
07626 case HueCommand:
07627 {
07628 static char
07629 hue_percent[MaxTextExtent] = "110";
07630
07631
07632
07633
07634 (void) XDialogWidget(display,windows,"Apply",
07635 "Enter percent change in image hue (0-200):",hue_percent);
07636 if (*hue_percent == '\0')
07637 break;
07638
07639
07640
07641 XSetCursorState(display,windows,MagickTrue);
07642 XCheckRefreshWindows(display,windows);
07643 (void) CopyMagickString(modulate_factors,"100.0/100.0/",MaxTextExtent);
07644 (void) ConcatenateMagickString(modulate_factors,hue_percent,
07645 MaxTextExtent);
07646 (void) ModulateImage(*image,modulate_factors);
07647 XSetCursorState(display,windows,MagickFalse);
07648 if (windows->image.orphan != MagickFalse)
07649 break;
07650 XConfigureImageColormap(display,resource_info,windows,*image);
07651 (void) XConfigureImage(display,resource_info,windows,*image);
07652 break;
07653 }
07654 case SaturationCommand:
07655 {
07656 static char
07657 saturation_percent[MaxTextExtent] = "110";
07658
07659
07660
07661
07662 (void) XDialogWidget(display,windows,"Apply",
07663 "Enter percent change in color saturation (0-200):",saturation_percent);
07664 if (*saturation_percent == '\0')
07665 break;
07666
07667
07668
07669 XSetCursorState(display,windows,MagickTrue);
07670 XCheckRefreshWindows(display,windows);
07671 (void) CopyMagickString(modulate_factors,"100.0/",MaxTextExtent);
07672 (void) ConcatenateMagickString(modulate_factors,saturation_percent,
07673 MaxTextExtent);
07674 (void) ModulateImage(*image,modulate_factors);
07675 XSetCursorState(display,windows,MagickFalse);
07676 if (windows->image.orphan != MagickFalse)
07677 break;
07678 XConfigureImageColormap(display,resource_info,windows,*image);
07679 (void) XConfigureImage(display,resource_info,windows,*image);
07680 break;
07681 }
07682 case BrightnessCommand:
07683 {
07684 static char
07685 brightness_percent[MaxTextExtent] = "110";
07686
07687
07688
07689
07690 (void) XDialogWidget(display,windows,"Apply",
07691 "Enter percent change in color brightness (0-200):",brightness_percent);
07692 if (*brightness_percent == '\0')
07693 break;
07694
07695
07696
07697 XSetCursorState(display,windows,MagickTrue);
07698 XCheckRefreshWindows(display,windows);
07699 (void) CopyMagickString(modulate_factors,brightness_percent,
07700 MaxTextExtent);
07701 (void) ModulateImage(*image,modulate_factors);
07702 XSetCursorState(display,windows,MagickFalse);
07703 if (windows->image.orphan != MagickFalse)
07704 break;
07705 XConfigureImageColormap(display,resource_info,windows,*image);
07706 (void) XConfigureImage(display,resource_info,windows,*image);
07707 break;
07708 }
07709 case GammaCommand:
07710 {
07711 static char
07712 factor[MaxTextExtent] = "1.6";
07713
07714
07715
07716
07717 (void) XDialogWidget(display,windows,"Gamma",
07718 "Enter gamma value (e.g. 1.0,1.0,1.6):",factor);
07719 if (*factor == '\0')
07720 break;
07721
07722
07723
07724 XSetCursorState(display,windows,MagickTrue);
07725 XCheckRefreshWindows(display,windows);
07726 (void) GammaImage(*image,factor);
07727 XSetCursorState(display,windows,MagickFalse);
07728 if (windows->image.orphan != MagickFalse)
07729 break;
07730 XConfigureImageColormap(display,resource_info,windows,*image);
07731 (void) XConfigureImage(display,resource_info,windows,*image);
07732 break;
07733 }
07734 case SpiffCommand:
07735 {
07736
07737
07738
07739 XSetCursorState(display,windows,MagickTrue);
07740 XCheckRefreshWindows(display,windows);
07741 (void) ContrastImage(*image,MagickTrue);
07742 XSetCursorState(display,windows,MagickFalse);
07743 if (windows->image.orphan != MagickFalse)
07744 break;
07745 XConfigureImageColormap(display,resource_info,windows,*image);
07746 (void) XConfigureImage(display,resource_info,windows,*image);
07747 break;
07748 }
07749 case DullCommand:
07750 {
07751
07752
07753
07754 XSetCursorState(display,windows,MagickTrue);
07755 XCheckRefreshWindows(display,windows);
07756 (void) ContrastImage(*image,MagickFalse);
07757 XSetCursorState(display,windows,MagickFalse);
07758 if (windows->image.orphan != MagickFalse)
07759 break;
07760 XConfigureImageColormap(display,resource_info,windows,*image);
07761 (void) XConfigureImage(display,resource_info,windows,*image);
07762 break;
07763 }
07764 case ContrastStretchCommand:
07765 {
07766 double
07767 black_point,
07768 white_point;
07769
07770 static char
07771 levels[MaxTextExtent] = "1%";
07772
07773
07774
07775
07776 (void) XDialogWidget(display,windows,"Contrast Stretch",
07777 "Enter black and white points:",levels);
07778 if (*levels == '\0')
07779 break;
07780
07781
07782
07783 XSetCursorState(display,windows,MagickTrue);
07784 XCheckRefreshWindows(display,windows);
07785 flags=ParseGeometry(levels,&geometry_info);
07786 black_point=geometry_info.rho;
07787 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma : black_point;
07788 if ((flags & PercentValue) != 0)
07789 {
07790 black_point*=(double) (*image)->columns*(*image)->rows/100.0;
07791 white_point*=(double) (*image)->columns*(*image)->rows/100.0;
07792 }
07793 white_point=(MagickRealType) (*image)->columns*(*image)->rows-white_point;
07794 (void) ContrastStretchImageChannel(*image,DefaultChannels,black_point,
07795 white_point);
07796 XSetCursorState(display,windows,MagickFalse);
07797 if (windows->image.orphan != MagickFalse)
07798 break;
07799 XConfigureImageColormap(display,resource_info,windows,*image);
07800 (void) XConfigureImage(display,resource_info,windows,*image);
07801 break;
07802 }
07803 case SigmoidalContrastCommand:
07804 {
07805 static char
07806 levels[MaxTextExtent] = "3x50%";
07807
07808
07809
07810
07811 (void) XDialogWidget(display,windows,"Sigmoidal Contrast",
07812 "Enter contrast and midpoint:",levels);
07813 if (*levels == '\0')
07814 break;
07815
07816
07817
07818 XSetCursorState(display,windows,MagickTrue);
07819 XCheckRefreshWindows(display,windows);
07820 (void) SigmoidalContrastImage(*image,MagickTrue,levels);
07821 XSetCursorState(display,windows,MagickFalse);
07822 if (windows->image.orphan != MagickFalse)
07823 break;
07824 XConfigureImageColormap(display,resource_info,windows,*image);
07825 (void) XConfigureImage(display,resource_info,windows,*image);
07826 break;
07827 }
07828 case NormalizeCommand:
07829 {
07830
07831
07832
07833 XSetCursorState(display,windows,MagickTrue);
07834 XCheckRefreshWindows(display,windows);
07835 (void) NormalizeImage(*image);
07836 XSetCursorState(display,windows,MagickFalse);
07837 if (windows->image.orphan != MagickFalse)
07838 break;
07839 XConfigureImageColormap(display,resource_info,windows,*image);
07840 (void) XConfigureImage(display,resource_info,windows,*image);
07841 break;
07842 }
07843 case EqualizeCommand:
07844 {
07845
07846
07847
07848 XSetCursorState(display,windows,MagickTrue);
07849 XCheckRefreshWindows(display,windows);
07850 (void) EqualizeImage(*image);
07851 XSetCursorState(display,windows,MagickFalse);
07852 if (windows->image.orphan != MagickFalse)
07853 break;
07854 XConfigureImageColormap(display,resource_info,windows,*image);
07855 (void) XConfigureImage(display,resource_info,windows,*image);
07856 break;
07857 }
07858 case NegateCommand:
07859 {
07860
07861
07862
07863 XSetCursorState(display,windows,MagickTrue);
07864 XCheckRefreshWindows(display,windows);
07865 (void) NegateImage(*image,MagickFalse);
07866 XSetCursorState(display,windows,MagickFalse);
07867 if (windows->image.orphan != MagickFalse)
07868 break;
07869 XConfigureImageColormap(display,resource_info,windows,*image);
07870 (void) XConfigureImage(display,resource_info,windows,*image);
07871 break;
07872 }
07873 case GrayscaleCommand:
07874 {
07875
07876
07877
07878 XSetCursorState(display,windows,MagickTrue);
07879 XCheckRefreshWindows(display,windows);
07880 (void) SetImageType(*image,(*image)->matte == MagickFalse ?
07881 GrayscaleType : GrayscaleMatteType);
07882 XSetCursorState(display,windows,MagickFalse);
07883 if (windows->image.orphan != MagickFalse)
07884 break;
07885 XConfigureImageColormap(display,resource_info,windows,*image);
07886 (void) XConfigureImage(display,resource_info,windows,*image);
07887 break;
07888 }
07889 case MapCommand:
07890 {
07891 Image
07892 *affinity_image;
07893
07894 static char
07895 filename[MaxTextExtent] = "\0";
07896
07897
07898
07899
07900 XFileBrowserWidget(display,windows,"Map",filename);
07901 if (*filename == '\0')
07902 break;
07903
07904
07905
07906 XSetCursorState(display,windows,MagickTrue);
07907 XCheckRefreshWindows(display,windows);
07908 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
07909 affinity_image=ReadImage(image_info,&(*image)->exception);
07910 if (affinity_image != (Image *) NULL)
07911 {
07912 (void) RemapImage(&quantize_info,*image,affinity_image);
07913 affinity_image=DestroyImage(affinity_image);
07914 }
07915 CatchException(&(*image)->exception);
07916 XSetCursorState(display,windows,MagickFalse);
07917 if (windows->image.orphan != MagickFalse)
07918 break;
07919 XConfigureImageColormap(display,resource_info,windows,*image);
07920 (void) XConfigureImage(display,resource_info,windows,*image);
07921 break;
07922 }
07923 case QuantizeCommand:
07924 {
07925 int
07926 status;
07927
07928 static char
07929 colors[MaxTextExtent] = "256";
07930
07931
07932
07933
07934 status=XDialogWidget(display,windows,"Quantize",
07935 "Maximum number of colors:",colors);
07936 if (*colors == '\0')
07937 break;
07938
07939
07940
07941 XSetCursorState(display,windows,MagickTrue);
07942 XCheckRefreshWindows(display,windows);
07943 quantize_info.number_colors=(unsigned long) atol(colors);
07944 quantize_info.dither=status != 0 ? MagickTrue : MagickFalse;
07945 (void) QuantizeImage(&quantize_info,*image);
07946 XSetCursorState(display,windows,MagickFalse);
07947 if (windows->image.orphan != MagickFalse)
07948 break;
07949 XConfigureImageColormap(display,resource_info,windows,*image);
07950 (void) XConfigureImage(display,resource_info,windows,*image);
07951 break;
07952 }
07953 case DespeckleCommand:
07954 {
07955 Image
07956 *despeckle_image;
07957
07958
07959
07960
07961 XSetCursorState(display,windows,MagickTrue);
07962 XCheckRefreshWindows(display,windows);
07963 despeckle_image=DespeckleImage(*image,&(*image)->exception);
07964 if (despeckle_image != (Image *) NULL)
07965 {
07966 *image=DestroyImage(*image);
07967 *image=despeckle_image;
07968 }
07969 CatchException(&(*image)->exception);
07970 XSetCursorState(display,windows,MagickFalse);
07971 if (windows->image.orphan != MagickFalse)
07972 break;
07973 XConfigureImageColormap(display,resource_info,windows,*image);
07974 (void) XConfigureImage(display,resource_info,windows,*image);
07975 break;
07976 }
07977 case EmbossCommand:
07978 {
07979 Image
07980 *emboss_image;
07981
07982 static char
07983 radius[MaxTextExtent] = "0.0x1.0";
07984
07985
07986
07987
07988 (void) XDialogWidget(display,windows,"Emboss",
07989 "Enter the emboss radius and standard deviation:",radius);
07990 if (*radius == '\0')
07991 break;
07992
07993
07994
07995 XSetCursorState(display,windows,MagickTrue);
07996 XCheckRefreshWindows(display,windows);
07997 flags=ParseGeometry(radius,&geometry_info);
07998 if ((flags & SigmaValue) == 0)
07999 geometry_info.sigma=1.0;
08000 emboss_image=EmbossImage(*image,geometry_info.rho,geometry_info.sigma,
08001 &(*image)->exception);
08002 if (emboss_image != (Image *) NULL)
08003 {
08004 *image=DestroyImage(*image);
08005 *image=emboss_image;
08006 }
08007 CatchException(&(*image)->exception);
08008 XSetCursorState(display,windows,MagickFalse);
08009 if (windows->image.orphan != MagickFalse)
08010 break;
08011 XConfigureImageColormap(display,resource_info,windows,*image);
08012 (void) XConfigureImage(display,resource_info,windows,*image);
08013 break;
08014 }
08015 case ReduceNoiseCommand:
08016 {
08017 Image
08018 *noise_image;
08019
08020 static char
08021 radius[MaxTextExtent] = "0";
08022
08023
08024
08025
08026 (void) XDialogWidget(display,windows,"Reduce Noise",
08027 "Enter the noise radius:",radius);
08028 if (*radius == '\0')
08029 break;
08030
08031
08032
08033 XSetCursorState(display,windows,MagickTrue);
08034 XCheckRefreshWindows(display,windows);
08035 flags=ParseGeometry(radius,&geometry_info);
08036 noise_image=ReduceNoiseImage(*image,geometry_info.rho,
08037 &(*image)->exception);
08038 if (noise_image != (Image *) NULL)
08039 {
08040 *image=DestroyImage(*image);
08041 *image=noise_image;
08042 }
08043 CatchException(&(*image)->exception);
08044 XSetCursorState(display,windows,MagickFalse);
08045 if (windows->image.orphan != MagickFalse)
08046 break;
08047 XConfigureImageColormap(display,resource_info,windows,*image);
08048 (void) XConfigureImage(display,resource_info,windows,*image);
08049 break;
08050 }
08051 case AddNoiseCommand:
08052 {
08053 char
08054 **noises;
08055
08056 Image
08057 *noise_image;
08058
08059 static char
08060 noise_type[MaxTextExtent] = "Gaussian";
08061
08062
08063
08064
08065 noises=GetMagickOptions(MagickNoiseOptions);
08066 if (noises == (char **) NULL)
08067 break;
08068 XListBrowserWidget(display,windows,&windows->widget,
08069 (const char **) noises,"Add Noise",
08070 "Select a type of noise to add to your image:",noise_type);
08071 noises=DestroyStringList(noises);
08072 if (*noise_type == '\0')
08073 break;
08074 XSetCursorState(display,windows,MagickTrue);
08075 XCheckRefreshWindows(display,windows);
08076 noise_image=AddNoiseImage(*image,(NoiseType) ParseMagickOption(
08077 MagickNoiseOptions,MagickFalse,noise_type),&(*image)->exception);
08078 if (noise_image != (Image *) NULL)
08079 {
08080 *image=DestroyImage(*image);
08081 *image=noise_image;
08082 }
08083 CatchException(&(*image)->exception);
08084 XSetCursorState(display,windows,MagickFalse);
08085 if (windows->image.orphan != MagickFalse)
08086 break;
08087 XConfigureImageColormap(display,resource_info,windows,*image);
08088 (void) XConfigureImage(display,resource_info,windows,*image);
08089 break;
08090 }
08091 case SharpenCommand:
08092 {
08093 Image
08094 *sharp_image;
08095
08096 static char
08097 radius[MaxTextExtent] = "0.0x1.0";
08098
08099
08100
08101
08102 (void) XDialogWidget(display,windows,"Sharpen",
08103 "Enter the sharpen radius and standard deviation:",radius);
08104 if (*radius == '\0')
08105 break;
08106
08107
08108
08109 XSetCursorState(display,windows,MagickTrue);
08110 XCheckRefreshWindows(display,windows);
08111 flags=ParseGeometry(radius,&geometry_info);
08112 sharp_image=SharpenImage(*image,geometry_info.rho,geometry_info.sigma,
08113 &(*image)->exception);
08114 if (sharp_image != (Image *) NULL)
08115 {
08116 *image=DestroyImage(*image);
08117 *image=sharp_image;
08118 }
08119 CatchException(&(*image)->exception);
08120 XSetCursorState(display,windows,MagickFalse);
08121 if (windows->image.orphan != MagickFalse)
08122 break;
08123 XConfigureImageColormap(display,resource_info,windows,*image);
08124 (void) XConfigureImage(display,resource_info,windows,*image);
08125 break;
08126 }
08127 case BlurCommand:
08128 {
08129 Image
08130 *blur_image;
08131
08132 static char
08133 radius[MaxTextExtent] = "0.0x1.0";
08134
08135
08136
08137
08138 (void) XDialogWidget(display,windows,"Blur",
08139 "Enter the blur radius and standard deviation:",radius);
08140 if (*radius == '\0')
08141 break;
08142
08143
08144
08145 XSetCursorState(display,windows,MagickTrue);
08146 XCheckRefreshWindows(display,windows);
08147 flags=ParseGeometry(radius,&geometry_info);
08148 blur_image=BlurImage(*image,geometry_info.rho,geometry_info.sigma,
08149 &(*image)->exception);
08150 if (blur_image != (Image *) NULL)
08151 {
08152 *image=DestroyImage(*image);
08153 *image=blur_image;
08154 }
08155 CatchException(&(*image)->exception);
08156 XSetCursorState(display,windows,MagickFalse);
08157 if (windows->image.orphan != MagickFalse)
08158 break;
08159 XConfigureImageColormap(display,resource_info,windows,*image);
08160 (void) XConfigureImage(display,resource_info,windows,*image);
08161 break;
08162 }
08163 case ThresholdCommand:
08164 {
08165 double
08166 threshold;
08167
08168 static char
08169 factor[MaxTextExtent] = "128";
08170
08171
08172
08173
08174 (void) XDialogWidget(display,windows,"Threshold",
08175 "Enter threshold value:",factor);
08176 if (*factor == '\0')
08177 break;
08178
08179
08180
08181 XSetCursorState(display,windows,MagickTrue);
08182 XCheckRefreshWindows(display,windows);
08183 threshold=StringToDouble(factor,QuantumRange);
08184 (void) BilevelImage(*image,threshold);
08185 XSetCursorState(display,windows,MagickFalse);
08186 if (windows->image.orphan != MagickFalse)
08187 break;
08188 XConfigureImageColormap(display,resource_info,windows,*image);
08189 (void) XConfigureImage(display,resource_info,windows,*image);
08190 break;
08191 }
08192 case EdgeDetectCommand:
08193 {
08194 Image
08195 *edge_image;
08196
08197 static char
08198 radius[MaxTextExtent] = "0";
08199
08200
08201
08202
08203 (void) XDialogWidget(display,windows,"Detect Edges",
08204 "Enter the edge detect radius:",radius);
08205 if (*radius == '\0')
08206 break;
08207
08208
08209
08210 XSetCursorState(display,windows,MagickTrue);
08211 XCheckRefreshWindows(display,windows);
08212 flags=ParseGeometry(radius,&geometry_info);
08213 edge_image=EdgeImage(*image,geometry_info.rho,&(*image)->exception);
08214 if (edge_image != (Image *) NULL)
08215 {
08216 *image=DestroyImage(*image);
08217 *image=edge_image;
08218 }
08219 CatchException(&(*image)->exception);
08220 XSetCursorState(display,windows,MagickFalse);
08221 if (windows->image.orphan != MagickFalse)
08222 break;
08223 XConfigureImageColormap(display,resource_info,windows,*image);
08224 (void) XConfigureImage(display,resource_info,windows,*image);
08225 break;
08226 }
08227 case SpreadCommand:
08228 {
08229 Image
08230 *spread_image;
08231
08232 static char
08233 amount[MaxTextExtent] = "2";
08234
08235
08236
08237
08238 (void) XDialogWidget(display,windows,"Spread",
08239 "Enter the displacement amount:",amount);
08240 if (*amount == '\0')
08241 break;
08242
08243
08244
08245 XSetCursorState(display,windows,MagickTrue);
08246 XCheckRefreshWindows(display,windows);
08247 flags=ParseGeometry(amount,&geometry_info);
08248 spread_image=EdgeImage(*image,geometry_info.rho,&(*image)->exception);
08249 if (spread_image != (Image *) NULL)
08250 {
08251 *image=DestroyImage(*image);
08252 *image=spread_image;
08253 }
08254 CatchException(&(*image)->exception);
08255 XSetCursorState(display,windows,MagickFalse);
08256 if (windows->image.orphan != MagickFalse)
08257 break;
08258 XConfigureImageColormap(display,resource_info,windows,*image);
08259 (void) XConfigureImage(display,resource_info,windows,*image);
08260 break;
08261 }
08262 case ShadeCommand:
08263 {
08264 Image
08265 *shade_image;
08266
08267 int
08268 status;
08269
08270 static char
08271 geometry[MaxTextExtent] = "30x30";
08272
08273
08274
08275
08276 status=XDialogWidget(display,windows,"Shade",
08277 "Enter the azimuth and elevation of the light source:",geometry);
08278 if (*geometry == '\0')
08279 break;
08280
08281
08282
08283 XSetCursorState(display,windows,MagickTrue);
08284 XCheckRefreshWindows(display,windows);
08285 flags=ParseGeometry(geometry,&geometry_info);
08286 if ((flags & SigmaValue) == 0)
08287 geometry_info.sigma=1.0;
08288 shade_image=ShadeImage(*image,status != 0 ? MagickFalse : MagickTrue,
08289 geometry_info.rho,geometry_info.sigma,&(*image)->exception);
08290 if (shade_image != (Image *) NULL)
08291 {
08292 *image=DestroyImage(*image);
08293 *image=shade_image;
08294 }
08295 CatchException(&(*image)->exception);
08296 XSetCursorState(display,windows,MagickFalse);
08297 if (windows->image.orphan != MagickFalse)
08298 break;
08299 XConfigureImageColormap(display,resource_info,windows,*image);
08300 (void) XConfigureImage(display,resource_info,windows,*image);
08301 break;
08302 }
08303 case RaiseCommand:
08304 {
08305 static char
08306 bevel_width[MaxTextExtent] = "10";
08307
08308
08309
08310
08311 (void) XDialogWidget(display,windows,"Raise","Bevel width:",bevel_width);
08312 if (*bevel_width == '\0')
08313 break;
08314
08315
08316
08317 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image);
08318 XSetCursorState(display,windows,MagickTrue);
08319 XCheckRefreshWindows(display,windows);
08320 (void) ParsePageGeometry(*image,bevel_width,&page_geometry,
08321 &(*image)->exception);
08322 (void) RaiseImage(*image,&page_geometry,MagickTrue);
08323 XSetCursorState(display,windows,MagickFalse);
08324 if (windows->image.orphan != MagickFalse)
08325 break;
08326 XConfigureImageColormap(display,resource_info,windows,*image);
08327 (void) XConfigureImage(display,resource_info,windows,*image);
08328 break;
08329 }
08330 case SegmentCommand:
08331 {
08332 static char
08333 threshold[MaxTextExtent] = "1.0x1.5";
08334
08335
08336
08337
08338 (void) XDialogWidget(display,windows,"Segment","Smooth threshold:",
08339 threshold);
08340 if (*threshold == '\0')
08341 break;
08342
08343
08344
08345 XSetCursorState(display,windows,MagickTrue);
08346 XCheckRefreshWindows(display,windows);
08347 flags=ParseGeometry(threshold,&geometry_info);
08348 if ((flags & SigmaValue) == 0)
08349 geometry_info.sigma=1.0;
08350 (void) SegmentImage(*image,RGBColorspace,MagickFalse,geometry_info.rho,
08351 geometry_info.sigma);
08352 XSetCursorState(display,windows,MagickFalse);
08353 if (windows->image.orphan != MagickFalse)
08354 break;
08355 XConfigureImageColormap(display,resource_info,windows,*image);
08356 (void) XConfigureImage(display,resource_info,windows,*image);
08357 break;
08358 }
08359 case SepiaToneCommand:
08360 {
08361 double
08362 threshold;
08363
08364 Image
08365 *sepia_image;
08366
08367 static char
08368 factor[MaxTextExtent] = "80%";
08369
08370
08371
08372
08373 (void) XDialogWidget(display,windows,"Sepia Tone",
08374 "Enter the sepia tone factor (0 - 99.9%):",factor);
08375 if (*factor == '\0')
08376 break;
08377
08378
08379
08380 XSetCursorState(display,windows,MagickTrue);
08381 XCheckRefreshWindows(display,windows);
08382 threshold=StringToDouble(factor,QuantumRange);
08383 sepia_image=SepiaToneImage(*image,threshold,&(*image)->exception);
08384 if (sepia_image != (Image *) NULL)
08385 {
08386 *image=DestroyImage(*image);
08387 *image=sepia_image;
08388 }
08389 CatchException(&(*image)->exception);
08390 XSetCursorState(display,windows,MagickFalse);
08391 if (windows->image.orphan != MagickFalse)
08392 break;
08393 XConfigureImageColormap(display,resource_info,windows,*image);
08394 (void) XConfigureImage(display,resource_info,windows,*image);
08395 break;
08396 }
08397 case SolarizeCommand:
08398 {
08399 double
08400 threshold;
08401
08402 static char
08403 factor[MaxTextExtent] = "60%";
08404
08405
08406
08407
08408 (void) XDialogWidget(display,windows,"Solarize",
08409 "Enter the solarize factor (0 - 99.9%):",factor);
08410 if (*factor == '\0')
08411 break;
08412
08413
08414
08415 XSetCursorState(display,windows,MagickTrue);
08416 XCheckRefreshWindows(display,windows);
08417 threshold=StringToDouble(factor,QuantumRange);
08418 (void) SolarizeImage(*image,threshold);
08419 XSetCursorState(display,windows,MagickFalse);
08420 if (windows->image.orphan != MagickFalse)
08421 break;
08422 XConfigureImageColormap(display,resource_info,windows,*image);
08423 (void) XConfigureImage(display,resource_info,windows,*image);
08424 break;
08425 }
08426 case SwirlCommand:
08427 {
08428 Image
08429 *swirl_image;
08430
08431 static char
08432 degrees[MaxTextExtent] = "60";
08433
08434
08435
08436
08437 (void) XDialogWidget(display,windows,"Swirl","Enter the swirl angle:",
08438 degrees);
08439 if (*degrees == '\0')
08440 break;
08441
08442
08443
08444 XSetCursorState(display,windows,MagickTrue);
08445 XCheckRefreshWindows(display,windows);
08446 flags=ParseGeometry(degrees,&geometry_info);
08447 swirl_image=SwirlImage(*image,geometry_info.rho,&(*image)->exception);
08448 if (swirl_image != (Image *) NULL)
08449 {
08450 *image=DestroyImage(*image);
08451 *image=swirl_image;
08452 }
08453 CatchException(&(*image)->exception);
08454 XSetCursorState(display,windows,MagickFalse);
08455 if (windows->image.orphan != MagickFalse)
08456 break;
08457 XConfigureImageColormap(display,resource_info,windows,*image);
08458 (void) XConfigureImage(display,resource_info,windows,*image);
08459 break;
08460 }
08461 case ImplodeCommand:
08462 {
08463 Image
08464 *implode_image;
08465
08466 static char
08467 factor[MaxTextExtent] = "0.3";
08468
08469
08470
08471
08472 (void) XDialogWidget(display,windows,"Implode",
08473 "Enter the implosion/explosion factor (-1.0 - 1.0):",factor);
08474 if (*factor == '\0')
08475 break;
08476
08477
08478
08479 XSetCursorState(display,windows,MagickTrue);
08480 XCheckRefreshWindows(display,windows);
08481 flags=ParseGeometry(factor,&geometry_info);
08482 implode_image=ImplodeImage(*image,geometry_info.rho,&(*image)->exception);
08483 if (implode_image != (Image *) NULL)
08484 {
08485 *image=DestroyImage(*image);
08486 *image=implode_image;
08487 }
08488 CatchException(&(*image)->exception);
08489 XSetCursorState(display,windows,MagickFalse);
08490 if (windows->image.orphan != MagickFalse)
08491 break;
08492 XConfigureImageColormap(display,resource_info,windows,*image);
08493 (void) XConfigureImage(display,resource_info,windows,*image);
08494 break;
08495 }
08496 case VignetteCommand:
08497 {
08498 Image
08499 *vignette_image;
08500
08501 static char
08502 geometry[MaxTextExtent] = "0x20";
08503
08504
08505
08506
08507 (void) XDialogWidget(display,windows,"Vignette",
08508 "Enter the radius, sigma, and x and y offsets:",geometry);
08509 if (*geometry == '\0')
08510 break;
08511
08512
08513
08514 XSetCursorState(display,windows,MagickTrue);
08515 XCheckRefreshWindows(display,windows);
08516 flags=ParseGeometry(geometry,&geometry_info);
08517 if ((flags & SigmaValue) == 0)
08518 geometry_info.sigma=1.0;
08519 if ((flags & XiValue) == 0)
08520 geometry_info.xi=0.1*(*image)->columns;
08521 if ((flags & PsiValue) == 0)
08522 geometry_info.psi=0.1*(*image)->rows;
08523 vignette_image=VignetteImage(*image,geometry_info.rho,geometry_info.sigma,
08524 (long) (geometry_info.xi+0.5),(long) (geometry_info.psi+0.5),
08525 &(*image)->exception);
08526 if (vignette_image != (Image *) NULL)
08527 {
08528 *image=DestroyImage(*image);
08529 *image=vignette_image;
08530 }
08531 CatchException(&(*image)->exception);
08532 XSetCursorState(display,windows,MagickFalse);
08533 if (windows->image.orphan != MagickFalse)
08534 break;
08535 XConfigureImageColormap(display,resource_info,windows,*image);
08536 (void) XConfigureImage(display,resource_info,windows,*image);
08537 break;
08538 }
08539 case WaveCommand:
08540 {
08541 Image
08542 *wave_image;
08543
08544 static char
08545 geometry[MaxTextExtent] = "25x150";
08546
08547
08548
08549
08550 (void) XDialogWidget(display,windows,"Wave",
08551 "Enter the amplitude and length of the wave:",geometry);
08552 if (*geometry == '\0')
08553 break;
08554
08555
08556
08557 XSetCursorState(display,windows,MagickTrue);
08558 XCheckRefreshWindows(display,windows);
08559 flags=ParseGeometry(geometry,&geometry_info);
08560 if ((flags & SigmaValue) == 0)
08561 geometry_info.sigma=1.0;
08562 wave_image=WaveImage(*image,geometry_info.rho,geometry_info.sigma,
08563 &(*image)->exception);
08564 if (wave_image != (Image *) NULL)
08565 {
08566 *image=DestroyImage(*image);
08567 *image=wave_image;
08568 }
08569 CatchException(&(*image)->exception);
08570 XSetCursorState(display,windows,MagickFalse);
08571 if (windows->image.orphan != MagickFalse)
08572 break;
08573 XConfigureImageColormap(display,resource_info,windows,*image);
08574 (void) XConfigureImage(display,resource_info,windows,*image);
08575 break;
08576 }
08577 case OilPaintCommand:
08578 {
08579 Image
08580 *paint_image;
08581
08582 static char
08583 radius[MaxTextExtent] = "0";
08584
08585
08586
08587
08588 (void) XDialogWidget(display,windows,"Oil Paint",
08589 "Enter the mask radius:",radius);
08590 if (*radius == '\0')
08591 break;
08592
08593
08594
08595 XSetCursorState(display,windows,MagickTrue);
08596 XCheckRefreshWindows(display,windows);
08597 flags=ParseGeometry(radius,&geometry_info);
08598 paint_image=OilPaintImage(*image,geometry_info.rho,&(*image)->exception);
08599 if (paint_image != (Image *) NULL)
08600 {
08601 *image=DestroyImage(*image);
08602 *image=paint_image;
08603 }
08604 CatchException(&(*image)->exception);
08605 XSetCursorState(display,windows,MagickFalse);
08606 if (windows->image.orphan != MagickFalse)
08607 break;
08608 XConfigureImageColormap(display,resource_info,windows,*image);
08609 (void) XConfigureImage(display,resource_info,windows,*image);
08610 break;
08611 }
08612 case CharcoalDrawCommand:
08613 {
08614 Image
08615 *charcoal_image;
08616
08617 static char
08618 radius[MaxTextExtent] = "0x1";
08619
08620
08621
08622
08623 (void) XDialogWidget(display,windows,"Charcoal Draw",
08624 "Enter the charcoal radius and sigma:",radius);
08625 if (*radius == '\0')
08626 break;
08627
08628
08629
08630 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image);
08631 XSetCursorState(display,windows,MagickTrue);
08632 XCheckRefreshWindows(display,windows);
08633 flags=ParseGeometry(radius,&geometry_info);
08634 if ((flags & SigmaValue) == 0)
08635 geometry_info.sigma=geometry_info.rho;
08636 charcoal_image=CharcoalImage(*image,geometry_info.rho,geometry_info.sigma,
08637 &(*image)->exception);
08638 if (charcoal_image != (Image *) NULL)
08639 {
08640 *image=DestroyImage(*image);
08641 *image=charcoal_image;
08642 }
08643 CatchException(&(*image)->exception);
08644 XSetCursorState(display,windows,MagickFalse);
08645 if (windows->image.orphan != MagickFalse)
08646 break;
08647 XConfigureImageColormap(display,resource_info,windows,*image);
08648 (void) XConfigureImage(display,resource_info,windows,*image);
08649 break;
08650 }
08651 case AnnotateCommand:
08652 {
08653
08654
08655
08656 status=XAnnotateEditImage(display,resource_info,windows,*image);
08657 if (status == MagickFalse)
08658 {
08659 XNoticeWidget(display,windows,"Unable to annotate X image",
08660 (*image)->filename);
08661 break;
08662 }
08663 break;
08664 }
08665 case DrawCommand:
08666 {
08667
08668
08669
08670 status=XDrawEditImage(display,resource_info,windows,image);
08671 if (status == MagickFalse)
08672 {
08673 XNoticeWidget(display,windows,"Unable to draw on the X image",
08674 (*image)->filename);
08675 break;
08676 }
08677 break;
08678 }
08679 case ColorCommand:
08680 {
08681
08682
08683
08684 status=XColorEditImage(display,resource_info,windows,image);
08685 if (status == MagickFalse)
08686 {
08687 XNoticeWidget(display,windows,"Unable to pixel edit X image",
08688 (*image)->filename);
08689 break;
08690 }
08691 break;
08692 }
08693 case MatteCommand:
08694 {
08695
08696
08697
08698 status=XMatteEditImage(display,resource_info,windows,image);
08699 if (status == MagickFalse)
08700 {
08701 XNoticeWidget(display,windows,"Unable to matte edit X image",
08702 (*image)->filename);
08703 break;
08704 }
08705 break;
08706 }
08707 case CompositeCommand:
08708 {
08709
08710
08711
08712 status=XCompositeImage(display,resource_info,windows,*image);
08713 if (status == MagickFalse)
08714 {
08715 XNoticeWidget(display,windows,"Unable to composite X image",
08716 (*image)->filename);
08717 break;
08718 }
08719 break;
08720 }
08721 case AddBorderCommand:
08722 {
08723 Image
08724 *border_image;
08725
08726 static char
08727 geometry[MaxTextExtent] = "6x6";
08728
08729
08730
08731
08732 XColorBrowserWidget(display,windows,"Select",color);
08733 if (*color == '\0')
08734 break;
08735 (void) XDialogWidget(display,windows,"Add Border",
08736 "Enter border geometry:",geometry);
08737 if (*geometry == '\0')
08738 break;
08739
08740
08741
08742 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image);
08743 XSetCursorState(display,windows,MagickTrue);
08744 XCheckRefreshWindows(display,windows);
08745 (void) QueryColorDatabase(color,&(*image)->border_color,
08746 &(*image)->exception);
08747 (void) ParsePageGeometry(*image,geometry,&page_geometry,
08748 &(*image)->exception);
08749 border_image=BorderImage(*image,&page_geometry,&(*image)->exception);
08750 if (border_image != (Image *) NULL)
08751 {
08752 *image=DestroyImage(*image);
08753 *image=border_image;
08754 }
08755 CatchException(&(*image)->exception);
08756 XSetCursorState(display,windows,MagickFalse);
08757 if (windows->image.orphan != MagickFalse)
08758 break;
08759 windows->image.window_changes.width=(int) (*image)->columns;
08760 windows->image.window_changes.height=(int) (*image)->rows;
08761 XConfigureImageColormap(display,resource_info,windows,*image);
08762 (void) XConfigureImage(display,resource_info,windows,*image);
08763 break;
08764 }
08765 case AddFrameCommand:
08766 {
08767 FrameInfo
08768 frame_info;
08769
08770 Image
08771 *frame_image;
08772
08773 static char
08774 geometry[MaxTextExtent] = "6x6";
08775
08776
08777
08778
08779 XColorBrowserWidget(display,windows,"Select",color);
08780 if (*color == '\0')
08781 break;
08782 (void) XDialogWidget(display,windows,"Add Frame","Enter frame geometry:",
08783 geometry);
08784 if (*geometry == '\0')
08785 break;
08786
08787
08788
08789 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image);
08790 XSetCursorState(display,windows,MagickTrue);
08791 XCheckRefreshWindows(display,windows);
08792 (void) QueryColorDatabase(color,&(*image)->matte_color,
08793 &(*image)->exception);
08794 (void) ParsePageGeometry(*image,geometry,&page_geometry,
08795 &(*image)->exception);
08796 frame_info.width=page_geometry.width;
08797 frame_info.height=page_geometry.height;
08798 frame_info.outer_bevel=page_geometry.x;
08799 frame_info.inner_bevel=page_geometry.y;
08800 frame_info.x=(long) frame_info.width;
08801 frame_info.y=(long) frame_info.height;
08802 frame_info.width=(*image)->columns+2*frame_info.width;
08803 frame_info.height=(*image)->rows+2*frame_info.height;
08804 frame_image=FrameImage(*image,&frame_info,&(*image)->exception);
08805 if (frame_image != (Image *) NULL)
08806 {
08807 *image=DestroyImage(*image);
08808 *image=frame_image;
08809 }
08810 CatchException(&(*image)->exception);
08811 XSetCursorState(display,windows,MagickFalse);
08812 if (windows->image.orphan != MagickFalse)
08813 break;
08814 windows->image.window_changes.width=(int) (*image)->columns;
08815 windows->image.window_changes.height=(int) (*image)->rows;
08816 XConfigureImageColormap(display,resource_info,windows,*image);
08817 (void) XConfigureImage(display,resource_info,windows,*image);
08818 break;
08819 }
08820 case CommentCommand:
08821 {
08822 const char
08823 *value;
08824
08825 FILE
08826 *file;
08827
08828 int
08829 unique_file;
08830
08831
08832
08833
08834 unique_file=AcquireUniqueFileResource(image_info->filename);
08835 if (unique_file == -1)
08836 XNoticeWidget(display,windows,"Unable to edit image comment",
08837 image_info->filename);
08838 value=GetImageProperty(*image,"comment");
08839 if (value == (char *) NULL)
08840 unique_file=close(unique_file)-1;
08841 else
08842 {
08843 register const char
08844 *p;
08845
08846 file=fdopen(unique_file,"w");
08847 if (file == (FILE *) NULL)
08848 {
08849 XNoticeWidget(display,windows,"Unable to edit image comment",
08850 image_info->filename);
08851 break;
08852 }
08853 for (p=value; *p != '\0'; p++)
08854 (void) fputc((int) *p,file);
08855 (void) fputc('\n',file);
08856 (void) fclose(file);
08857 }
08858 XSetCursorState(display,windows,MagickTrue);
08859 XCheckRefreshWindows(display,windows);
08860 status=InvokeDelegate(image_info,*image,"edit",(char *) NULL,
08861 &(*image)->exception);
08862 if (status == MagickFalse)
08863 XNoticeWidget(display,windows,"Unable to edit image comment",
08864 (char *) NULL);
08865 else
08866 {
08867 char
08868 *comment;
08869
08870 comment=FileToString(image_info->filename,~0UL,&(*image)->exception);
08871 if (comment != (char *) NULL)
08872 {
08873 (void) SetImageProperty(*image,"comment",comment);
08874 (*image)->taint=MagickTrue;
08875 }
08876 }
08877 (void) RelinquishUniqueFileResource(image_info->filename);
08878 XSetCursorState(display,windows,MagickFalse);
08879 break;
08880 }
08881 case LaunchCommand:
08882 {
08883
08884
08885
08886 XSetCursorState(display,windows,MagickTrue);
08887 XCheckRefreshWindows(display,windows);
08888 (void) AcquireUniqueFilename(filename);
08889 (void) FormatMagickString((*image)->filename,MaxTextExtent,"launch:%s",
08890 filename);
08891 status=WriteImage(image_info,*image);
08892 if (status == MagickFalse)
08893 XNoticeWidget(display,windows,"Unable to launch image editor",
08894 (char *) NULL);
08895 else
08896 {
08897 nexus=ReadImage(resource_info->image_info,&(*image)->exception);
08898 CatchException(&(*image)->exception);
08899 XClientMessage(display,windows->image.id,windows->im_protocols,
08900 windows->im_next_image,CurrentTime);
08901 }
08902 (void) RelinquishUniqueFileResource(filename);
08903 XSetCursorState(display,windows,MagickFalse);
08904 break;
08905 }
08906 case RegionofInterestCommand:
08907 {
08908
08909
08910
08911 (void) XROIImage(display,resource_info,windows,image);
08912 break;
08913 }
08914 case InfoCommand:
08915 break;
08916 case ZoomCommand:
08917 {
08918
08919
08920
08921 if (windows->magnify.mapped != MagickFalse)
08922 (void) XRaiseWindow(display,windows->magnify.id);
08923 else
08924 {
08925
08926
08927
08928 XSetCursorState(display,windows,MagickTrue);
08929 (void) XMapRaised(display,windows->magnify.id);
08930 XSetCursorState(display,windows,MagickFalse);
08931 }
08932 break;
08933 }
08934 case ShowPreviewCommand:
08935 {
08936 char
08937 **previews;
08938
08939 static char
08940 preview_type[MaxTextExtent] = "Gamma";
08941
08942
08943
08944
08945 previews=GetMagickOptions(MagickPreviewOptions);
08946 if (previews == (char **) NULL)
08947 break;
08948 XListBrowserWidget(display,windows,&windows->widget,
08949 (const char **) previews,"Preview",
08950 "Select an enhancement, effect, or F/X:",preview_type);
08951 previews=DestroyStringList(previews);
08952 if (*preview_type == '\0')
08953 break;
08954
08955
08956
08957 XSetCursorState(display,windows,MagickTrue);
08958 XCheckRefreshWindows(display,windows);
08959 image_info->preview_type=(PreviewType)
08960 ParseMagickOption(MagickPreviewOptions,MagickFalse,preview_type);
08961 image_info->group=(long) windows->image.id;
08962 (void) DeleteImageProperty(*image,"label");
08963 (void) SetImageProperty(*image,"label","Preview");
08964 (void) AcquireUniqueFilename(filename);
08965 (void) FormatMagickString((*image)->filename,MaxTextExtent,"preview:%s",
08966 filename);
08967 status=WriteImage(image_info,*image);
08968 (void) FormatMagickString((*image)->filename,MaxTextExtent,"show:%s",
08969 filename);
08970 status=WriteImage(image_info,*image);
08971 if (status == MagickFalse)
08972 XNoticeWidget(display,windows,"Unable to show image preview",
08973 (*image)->filename);
08974 XDelay(display,1500);
08975 XSetCursorState(display,windows,MagickFalse);
08976 break;
08977 }
08978 case ShowHistogramCommand:
08979 {
08980
08981
08982
08983 XSetCursorState(display,windows,MagickTrue);
08984 XCheckRefreshWindows(display,windows);
08985 image_info->group=(long) windows->image.id;
08986 (void) DeleteImageProperty(*image,"label");
08987 (void) SetImageProperty(*image,"label","Histogram");
08988 (void) AcquireUniqueFilename(filename);
08989 (void) FormatMagickString((*image)->filename,MaxTextExtent,"histogram:%s",
08990 filename);
08991 status=WriteImage(image_info,*image);
08992 (void) FormatMagickString((*image)->filename,MaxTextExtent,"show:%s",
08993 filename);
08994 status=WriteImage(image_info,*image);
08995 if (status == MagickFalse)
08996 XNoticeWidget(display,windows,"Unable to show histogram",
08997 (*image)->filename);
08998 XDelay(display,1500);
08999 XSetCursorState(display,windows,MagickFalse);
09000 break;
09001 }
09002 case ShowMatteCommand:
09003 {
09004 if ((*image)->matte == MagickFalse)
09005 {
09006 XNoticeWidget(display,windows,
09007 "Image does not have any matte information",(*image)->filename);
09008 break;
09009 }
09010
09011
09012
09013 XSetCursorState(display,windows,MagickTrue);
09014 XCheckRefreshWindows(display,windows);
09015 image_info->group=(long) windows->image.id;
09016 (void) DeleteImageProperty(*image,"label");
09017 (void) SetImageProperty(*image,"label","Matte");
09018 (void) AcquireUniqueFilename(filename);
09019 (void) FormatMagickString((*image)->filename,MaxTextExtent,"matte:%s",
09020 filename);
09021 status=WriteImage(image_info,*image);
09022 (void) FormatMagickString((*image)->filename,MaxTextExtent,"show:%s",
09023 filename);
09024 status=WriteImage(image_info,*image);
09025 if (status == MagickFalse)
09026 XNoticeWidget(display,windows,"Unable to show matte",
09027 (*image)->filename);
09028 XDelay(display,1500);
09029 XSetCursorState(display,windows,MagickFalse);
09030 break;
09031 }
09032 case BackgroundCommand:
09033 {
09034
09035
09036
09037 status=XBackgroundImage(display,resource_info,windows,image);
09038 if (status == MagickFalse)
09039 break;
09040 nexus=CloneImage(*image,0,0,MagickTrue,&(*image)->exception);
09041 if (nexus != (Image *) NULL)
09042 XClientMessage(display,windows->image.id,windows->im_protocols,
09043 windows->im_next_image,CurrentTime);
09044 break;
09045 }
09046 case SlideShowCommand:
09047 {
09048 static char
09049 delay[MaxTextExtent] = "5";
09050
09051
09052
09053
09054 (void) XDialogWidget(display,windows,"Slide Show",
09055 "Pause how many 1/100ths of a second between images:",delay);
09056 if (*delay == '\0')
09057 break;
09058 resource_info->delay=(unsigned long) atol(delay);
09059 XClientMessage(display,windows->image.id,windows->im_protocols,
09060 windows->im_next_image,CurrentTime);
09061 break;
09062 }
09063 case PreferencesCommand:
09064 {
09065
09066
09067
09068 status=XPreferencesWidget(display,resource_info,windows);
09069 if (status == MagickFalse)
09070 break;
09071 nexus=CloneImage(*image,0,0,MagickTrue,&(*image)->exception);
09072 if (nexus != (Image *) NULL)
09073 XClientMessage(display,windows->image.id,windows->im_protocols,
09074 windows->im_next_image,CurrentTime);
09075 break;
09076 }
09077 case HelpCommand:
09078 {
09079
09080
09081
09082 XTextViewWidget(display,resource_info,windows,MagickFalse,
09083 "Help Viewer - Display",DisplayHelp);
09084 break;
09085 }
09086 case BrowseDocumentationCommand:
09087 {
09088 Atom
09089 mozilla_atom;
09090
09091 Window
09092 mozilla_window,
09093 root_window;
09094
09095
09096
09097
09098 root_window=XRootWindow(display,XDefaultScreen(display));
09099 mozilla_atom=XInternAtom(display,"_MOZILLA_VERSION",MagickFalse);
09100 mozilla_window=XWindowByProperty(display,root_window,mozilla_atom);
09101 if (mozilla_window != (Window) NULL)
09102 {
09103 char
09104 command[MaxTextExtent],
09105 *url;
09106
09107
09108
09109
09110 url=GetMagickHomeURL();
09111 (void) FormatMagickString(command,MaxTextExtent,
09112 "openurl(%s,new-tab)",url);
09113 url=DestroyString(url);
09114 mozilla_atom=XInternAtom(display,"_MOZILLA_COMMAND",MagickFalse);
09115 (void) XChangeProperty(display,mozilla_window,mozilla_atom,XA_STRING,
09116 8,PropModeReplace,(unsigned char *) command,(int) strlen(command));
09117 XSetCursorState(display,windows,MagickFalse);
09118 break;
09119 }
09120 XSetCursorState(display,windows,MagickTrue);
09121 XCheckRefreshWindows(display,windows);
09122 status=InvokeDelegate(image_info,*image,"browse",(char *) NULL,
09123 &(*image)->exception);
09124 if (status == MagickFalse)
09125 XNoticeWidget(display,windows,"Unable to browse documentation",
09126 (char *) NULL);
09127 XDelay(display,1500);
09128 XSetCursorState(display,windows,MagickFalse);
09129 break;
09130 }
09131 case VersionCommand:
09132 {
09133 XNoticeWidget(display,windows,GetMagickVersion((unsigned long *) NULL),
09134 GetMagickCopyright());
09135 break;
09136 }
09137 case SaveToUndoBufferCommand:
09138 break;
09139 default:
09140 {
09141 (void) XBell(display,0);
09142 break;
09143 }
09144 }
09145 image_info=DestroyImageInfo(image_info);
09146 return(nexus);
09147 }
09148
09149
09150
09151
09152
09153
09154
09155
09156
09157
09158
09159
09160
09161
09162
09163
09164
09165
09166
09167
09168
09169
09170
09171
09172
09173
09174
09175
09176
09177
09178 static void XMagnifyImage(Display *display,XWindows *windows,XEvent *event)
09179 {
09180 char
09181 text[MaxTextExtent];
09182
09183 register int
09184 x,
09185 y;
09186
09187 unsigned long
09188 state;
09189
09190
09191
09192
09193 (void) XCheckDefineCursor(display,windows->image.id,windows->magnify.cursor);
09194 state=DefaultState;
09195 x=event->xbutton.x;
09196 y=event->xbutton.y;
09197 windows->magnify.x=windows->image.x+x;
09198 windows->magnify.y=windows->image.y+y;
09199 do
09200 {
09201
09202
09203
09204 if (windows->info.mapped != MagickFalse)
09205 {
09206 if ((x < (int) (windows->info.x+windows->info.width)) &&
09207 (y < (int) (windows->info.y+windows->info.height)))
09208 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
09209 }
09210 else
09211 if ((x > (int) (windows->info.x+windows->info.width)) ||
09212 (y > (int) (windows->info.y+windows->info.height)))
09213 (void) XMapWindow(display,windows->info.id);
09214 if (windows->info.mapped != MagickFalse)
09215 {
09216
09217
09218
09219 (void) FormatMagickString(text,MaxTextExtent," %+d%+d ",
09220 windows->magnify.x,windows->magnify.y);
09221 XInfoWidget(display,windows,text);
09222 }
09223
09224
09225
09226 XScreenEvent(display,windows,event);
09227 switch (event->type)
09228 {
09229 case ButtonPress:
09230 break;
09231 case ButtonRelease:
09232 {
09233
09234
09235
09236 x=event->xbutton.x;
09237 y=event->xbutton.y;
09238 state|=ExitState;
09239 break;
09240 }
09241 case Expose:
09242 break;
09243 case MotionNotify:
09244 {
09245 x=event->xmotion.x;
09246 y=event->xmotion.y;
09247 break;
09248 }
09249 default:
09250 break;
09251 }
09252
09253
09254
09255 if (x < 0)
09256 x=0;
09257 else
09258 if (x >= (int) windows->image.width)
09259 x=(int) windows->image.width-1;
09260 if (y < 0)
09261 y=0;
09262 else
09263 if (y >= (int) windows->image.height)
09264 y=(int) windows->image.height-1;
09265 } while ((state & ExitState) == 0);
09266
09267
09268
09269 XSetCursorState(display,windows,MagickFalse);
09270 }
09271
09272
09273
09274
09275
09276
09277
09278
09279
09280
09281
09282
09283
09284
09285
09286
09287
09288
09289
09290
09291
09292
09293
09294
09295
09296
09297
09298
09299
09300
09301
09302
09303
09304 static void XMagnifyWindowCommand(Display *display,XWindows *windows,
09305 const MagickStatusType state,const KeySym key_symbol)
09306 {
09307 unsigned int
09308 quantum;
09309
09310
09311
09312
09313 quantum=1;
09314 if ((state & Mod1Mask) != 0)
09315 quantum=10;
09316 switch ((int) key_symbol)
09317 {
09318 case QuitCommand:
09319 {
09320 (void) XWithdrawWindow(display,windows->magnify.id,
09321 windows->magnify.screen);
09322 break;
09323 }
09324 case XK_Home:
09325 case XK_KP_Home:
09326 {
09327 windows->magnify.x=(int) windows->image.width/2;
09328 windows->magnify.y=(int) windows->image.height/2;
09329 break;
09330 }
09331 case XK_Left:
09332 case XK_KP_Left:
09333 {
09334 if (windows->magnify.x > 0)
09335 windows->magnify.x-=quantum;
09336 break;
09337 }
09338 case XK_Up:
09339 case XK_KP_Up:
09340 {
09341 if (windows->magnify.y > 0)
09342 windows->magnify.y-=quantum;
09343 break;
09344 }
09345 case XK_Right:
09346 case XK_KP_Right:
09347 {
09348 if (windows->magnify.x < (int) (windows->image.ximage->width-1))
09349 windows->magnify.x+=quantum;
09350 break;
09351 }
09352 case XK_Down:
09353 case XK_KP_Down:
09354 {
09355 if (windows->magnify.y < (int) (windows->image.ximage->height-1))
09356 windows->magnify.y+=quantum;
09357 break;
09358 }
09359 case XK_0:
09360 case XK_1:
09361 case XK_2:
09362 case XK_3:
09363 case XK_4:
09364 case XK_5:
09365 case XK_6:
09366 case XK_7:
09367 case XK_8:
09368 case XK_9:
09369 {
09370 windows->magnify.data=(key_symbol-XK_0);
09371 break;
09372 }
09373 case XK_KP_0:
09374 case XK_KP_1:
09375 case XK_KP_2:
09376 case XK_KP_3:
09377 case XK_KP_4:
09378 case XK_KP_5:
09379 case XK_KP_6:
09380 case XK_KP_7:
09381 case XK_KP_8:
09382 case XK_KP_9:
09383 {
09384 windows->magnify.data=(key_symbol-XK_KP_0);
09385 break;
09386 }
09387 default:
09388 break;
09389 }
09390 XMakeMagnifyImage(display,windows);
09391 }
09392
09393
09394
09395
09396
09397
09398
09399
09400
09401
09402
09403
09404
09405
09406
09407
09408
09409
09410
09411
09412
09413
09414
09415
09416
09417
09418
09419
09420
09421
09422
09423
09424
09425 static void XMakePanImage(Display *display,XResourceInfo *resource_info,
09426 XWindows *windows,Image *image)
09427 {
09428 MagickStatusType
09429 status;
09430
09431
09432
09433
09434 XSetCursorState(display,windows,MagickTrue);
09435 XCheckRefreshWindows(display,windows);
09436 windows->pan.x=windows->image.x;
09437 windows->pan.y=windows->image.y;
09438 status=XMakeImage(display,resource_info,&windows->pan,image,
09439 windows->pan.width,windows->pan.height);
09440 if (status == MagickFalse)
09441 ThrowXWindowFatalException(XServerError,image->exception.reason,
09442 image->exception.description);
09443 (void) XSetWindowBackgroundPixmap(display,windows->pan.id,
09444 windows->pan.pixmap);
09445 (void) XClearWindow(display,windows->pan.id);
09446 XDrawPanRectangle(display,windows);
09447 XSetCursorState(display,windows,MagickFalse);
09448 }
09449
09450
09451
09452
09453
09454
09455
09456
09457
09458
09459
09460
09461
09462
09463
09464
09465
09466
09467
09468
09469
09470
09471
09472
09473
09474
09475
09476
09477
09478
09479
09480
09481
09482
09483 static MagickBooleanType XMatteEditImage(Display *display,
09484 XResourceInfo *resource_info,XWindows *windows,Image **image)
09485 {
09486 static char
09487 matte[MaxTextExtent] = "0";
09488
09489 static const char
09490 *MatteEditMenu[] =
09491 {
09492 "Method",
09493 "Border Color",
09494 "Fuzz",
09495 "Matte Value",
09496 "Undo",
09497 "Help",
09498 "Dismiss",
09499 (char *) NULL
09500 };
09501
09502 static const ModeType
09503 MatteEditCommands[] =
09504 {
09505 MatteEditMethod,
09506 MatteEditBorderCommand,
09507 MatteEditFuzzCommand,
09508 MatteEditValueCommand,
09509 MatteEditUndoCommand,
09510 MatteEditHelpCommand,
09511 MatteEditDismissCommand
09512 };
09513
09514 static PaintMethod
09515 method = PointMethod;
09516
09517 static XColor
09518 border_color = { 0, 0, 0, 0, 0, 0 };
09519
09520 char
09521 command[MaxTextExtent],
09522 text[MaxTextExtent];
09523
09524 Cursor
09525 cursor;
09526
09527 int
09528 entry,
09529 id,
09530 x,
09531 x_offset,
09532 y,
09533 y_offset;
09534
09535 register int
09536 i;
09537
09538 register PixelPacket
09539 *q;
09540
09541 unsigned int
09542 height,
09543 width;
09544
09545 unsigned long
09546 state;
09547
09548 XEvent
09549 event;
09550
09551
09552
09553
09554 (void) CloneString(&windows->command.name,"Matte Edit");
09555 windows->command.data=4;
09556 (void) XCommandWidget(display,windows,MatteEditMenu,(XEvent *) NULL);
09557 (void) XMapRaised(display,windows->command.id);
09558 XClientMessage(display,windows->image.id,windows->im_protocols,
09559 windows->im_update_widget,CurrentTime);
09560
09561
09562
09563 cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap,
09564 resource_info->background_color,resource_info->foreground_color);
09565 (void) XCheckDefineCursor(display,windows->image.id,cursor);
09566
09567
09568
09569 XQueryPosition(display,windows->image.id,&x,&y);
09570 (void) XSelectInput(display,windows->image.id,
09571 windows->image.attributes.event_mask | PointerMotionMask);
09572 state=DefaultState;
09573 do
09574 {
09575 if (windows->info.mapped != MagickFalse)
09576 {
09577
09578
09579
09580 (void) FormatMagickString(text,MaxTextExtent," %+d%+d ",
09581 x+windows->image.x,y+windows->image.y);
09582 XInfoWidget(display,windows,text);
09583 }
09584
09585
09586
09587 XScreenEvent(display,windows,&event);
09588 if (event.xany.window == windows->command.id)
09589 {
09590
09591
09592
09593 id=XCommandWidget(display,windows,MatteEditMenu,&event);
09594 if (id < 0)
09595 {
09596 (void) XCheckDefineCursor(display,windows->image.id,cursor);
09597 continue;
09598 }
09599 switch (MatteEditCommands[id])
09600 {
09601 case MatteEditMethod:
09602 {
09603 char
09604 **methods;
09605
09606
09607
09608
09609 methods=GetMagickOptions(MagickMethodOptions);
09610 if (methods == (char **) NULL)
09611 break;
09612 entry=XMenuWidget(display,windows,MatteEditMenu[id],
09613 (const char **) methods,command);
09614 if (entry >= 0)
09615 method=(PaintMethod) ParseMagickOption(MagickMethodOptions,
09616 MagickFalse,methods[entry]);
09617 methods=DestroyStringList(methods);
09618 break;
09619 }
09620 case MatteEditBorderCommand:
09621 {
09622 const char
09623 *ColorMenu[MaxNumberPens];
09624
09625 int
09626 pen_number;
09627
09628
09629
09630
09631 for (i=0; i < (int) (MaxNumberPens-2); i++)
09632 ColorMenu[i]=resource_info->pen_colors[i];
09633 ColorMenu[MaxNumberPens-2]="Browser...";
09634 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
09635
09636
09637
09638 pen_number=XMenuWidget(display,windows,MatteEditMenu[id],
09639 (const char **) ColorMenu,command);
09640 if (pen_number < 0)
09641 break;
09642 if (pen_number == (MaxNumberPens-2))
09643 {
09644 static char
09645 color_name[MaxTextExtent] = "gray";
09646
09647
09648
09649
09650 resource_info->pen_colors[pen_number]=color_name;
09651 XColorBrowserWidget(display,windows,"Select",color_name);
09652 if (*color_name == '\0')
09653 break;
09654 }
09655
09656
09657
09658 (void) XParseColor(display,windows->map_info->colormap,
09659 resource_info->pen_colors[pen_number],&border_color);
09660 break;
09661 }
09662 case MatteEditFuzzCommand:
09663 {
09664 static char
09665 fuzz[MaxTextExtent];
09666
09667 static const char
09668 *FuzzMenu[] =
09669 {
09670 "0%",
09671 "2%",
09672 "5%",
09673 "10%",
09674 "15%",
09675 "Dialog...",
09676 (char *) NULL,
09677 };
09678
09679
09680
09681
09682 entry=XMenuWidget(display,windows,MatteEditMenu[id],FuzzMenu,
09683 command);
09684 if (entry < 0)
09685 break;
09686 if (entry != 5)
09687 {
09688 (*image)->fuzz=StringToDouble(FuzzMenu[entry],1.0*QuantumRange+
09689 1.0);
09690 break;
09691 }
09692 (void) CopyMagickString(fuzz,"20%",MaxTextExtent);
09693 (void) XDialogWidget(display,windows,"Ok",
09694 "Enter fuzz factor (0.0 - 99.9%):",fuzz);
09695 if (*fuzz == '\0')
09696 break;
09697 (void) ConcatenateMagickString(fuzz,"%",MaxTextExtent);
09698 (*image)->fuzz=StringToDouble(fuzz,1.0*QuantumRange+1.0);
09699 break;
09700 }
09701 case MatteEditValueCommand:
09702 {
09703 static char
09704 message[MaxTextExtent];
09705
09706 static const char
09707 *MatteMenu[] =
09708 {
09709 "Opaque",
09710 "Transparent",
09711 "Dialog...",
09712 (char *) NULL,
09713 };
09714
09715
09716
09717
09718 entry=XMenuWidget(display,windows,MatteEditMenu[id],MatteMenu,
09719 command);
09720 if (entry < 0)
09721 break;
09722 if (entry != 2)
09723 {
09724 (void) FormatMagickString(matte,MaxTextExtent,QuantumFormat,
09725 OpaqueOpacity);
09726 if (LocaleCompare(MatteMenu[entry],"Transparent") == 0)
09727 (void) FormatMagickString(matte,MaxTextExtent,QuantumFormat,
09728 (Quantum) TransparentOpacity);
09729 break;
09730 }
09731 (void) FormatMagickString(message,MaxTextExtent,
09732 "Enter matte value (0 - " QuantumFormat "):",(Quantum)
09733 QuantumRange);
09734 (void) XDialogWidget(display,windows,"Matte",message,matte);
09735 if (*matte == '\0')
09736 break;
09737 break;
09738 }
09739 case MatteEditUndoCommand:
09740 {
09741 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
09742 image);
09743 break;
09744 }
09745 case MatteEditHelpCommand:
09746 {
09747 XTextViewWidget(display,resource_info,windows,MagickFalse,
09748 "Help Viewer - Matte Edit",ImageMatteEditHelp);
09749 break;
09750 }
09751 case MatteEditDismissCommand:
09752 {
09753
09754
09755
09756 state|=EscapeState;
09757 state|=ExitState;
09758 break;
09759 }
09760 default:
09761 break;
09762 }
09763 (void) XCheckDefineCursor(display,windows->image.id,cursor);
09764 continue;
09765 }
09766 switch (event.type)
09767 {
09768 case ButtonPress:
09769 {
09770 if (event.xbutton.button != Button1)
09771 break;
09772 if ((event.xbutton.window != windows->image.id) &&
09773 (event.xbutton.window != windows->magnify.id))
09774 break;
09775
09776
09777
09778 x=event.xbutton.x;
09779 y=event.xbutton.y;
09780 (void) XMagickCommand(display,resource_info,windows,
09781 SaveToUndoBufferCommand,image);
09782 state|=UpdateConfigurationState;
09783 break;
09784 }
09785 case ButtonRelease:
09786 {
09787 if (event.xbutton.button != Button1)
09788 break;
09789 if ((event.xbutton.window != windows->image.id) &&
09790 (event.xbutton.window != windows->magnify.id))
09791 break;
09792
09793
09794
09795 x=event.xbutton.x;
09796 y=event.xbutton.y;
09797 XConfigureImageColormap(display,resource_info,windows,*image);
09798 (void) XConfigureImage(display,resource_info,windows,*image);
09799 XInfoWidget(display,windows,text);
09800 (void) XCheckDefineCursor(display,windows->image.id,cursor);
09801 state&=(~UpdateConfigurationState);
09802 break;
09803 }
09804 case Expose:
09805 break;
09806 case KeyPress:
09807 {
09808 char
09809 command[MaxTextExtent];
09810
09811 KeySym
09812 key_symbol;
09813
09814 if (event.xkey.window == windows->magnify.id)
09815 {
09816 Window
09817 window;
09818
09819 window=windows->magnify.id;
09820 while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ;
09821
09822 }
09823 if (event.xkey.window != windows->image.id)
09824 break;
09825
09826
09827
09828 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
09829 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
09830 switch ((int) key_symbol)
09831 {
09832 case XK_Escape:
09833 case XK_F20:
09834 {
09835
09836
09837
09838 state|=ExitState;
09839 break;
09840 }
09841 case XK_F1:
09842 case XK_Help:
09843 {
09844 XTextViewWidget(display,resource_info,windows,MagickFalse,
09845 "Help Viewer - Matte Edit",ImageMatteEditHelp);
09846 break;
09847 }
09848 default:
09849 {
09850 (void) XBell(display,0);
09851 break;
09852 }
09853 }
09854 break;
09855 }
09856 case MotionNotify:
09857 {
09858
09859
09860
09861 x=event.xmotion.x;
09862 y=event.xmotion.y;
09863 if (windows->info.mapped != MagickFalse)
09864 {
09865 if ((x < (int) (windows->info.x+windows->info.width)) &&
09866 (y < (int) (windows->info.y+windows->info.height)))
09867 (void) XWithdrawWindow(display,windows->info.id,
09868 windows->info.screen);
09869 }
09870 else
09871 if ((x > (int) (windows->info.x+windows->info.width)) ||
09872 (y > (int) (windows->info.y+windows->info.height)))
09873 (void) XMapWindow(display,windows->info.id);
09874 break;
09875 }
09876 default:
09877 break;
09878 }
09879 if (event.xany.window == windows->magnify.id)
09880 {
09881 x=windows->magnify.x-windows->image.x;
09882 y=windows->magnify.y-windows->image.y;
09883 }
09884 x_offset=x;
09885 y_offset=y;
09886 if ((state & UpdateConfigurationState) != 0)
09887 {
09888 ExceptionInfo
09889 *exception;
09890
09891 int
09892 x,
09893 y;
09894
09895
09896
09897
09898 (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1,
09899 MagickTrue);
09900 XPutPixel(windows->image.ximage,x_offset,y_offset,
09901 windows->pixel_info->background_color.pixel);
09902 width=(unsigned int) (*image)->columns;
09903 height=(unsigned int) (*image)->rows;
09904 x=0;
09905 y=0;
09906 if (windows->image.crop_geometry != (char *) NULL)
09907 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
09908 &width,&height);
09909 x_offset=(int)
09910 (width*(windows->image.x+x_offset)/windows->image.ximage->width+x);
09911 y_offset=(int)
09912 (height*(windows->image.y+y_offset)/windows->image.ximage->height+y);
09913 if ((x_offset < 0) || (y_offset < 0))
09914 continue;
09915 if ((x_offset >= (int) (*image)->columns) ||
09916 (y_offset >= (int) (*image)->rows))
09917 continue;
09918 if (SetImageStorageClass(*image,DirectClass) == MagickFalse)
09919 return(MagickFalse);
09920 (*image)->matte=MagickTrue;
09921 exception=(&(*image)->exception);
09922 switch (method)
09923 {
09924 case PointMethod:
09925 default:
09926 {
09927
09928
09929
09930 q=GetAuthenticPixels(*image,x_offset,y_offset,1,1,exception);
09931 if (q == (PixelPacket *) NULL)
09932 break;
09933 q->opacity=(Quantum) atol(matte);
09934 (void) SyncAuthenticPixels(*image,exception);
09935 break;
09936 }
09937 case ReplaceMethod:
09938 {
09939 PixelPacket
09940 target;
09941
09942
09943
09944
09945 (void) GetOneVirtualPixel(*image,x_offset,y_offset,&target,
09946 exception);
09947 for (y=0; y < (long) (*image)->rows; y++)
09948 {
09949 q=GetAuthenticPixels(*image,0,y,(*image)->columns,1,
09950 &(*image)->exception);
09951 if (q == (PixelPacket *) NULL)
09952 break;
09953 for (x=0; x < (int) (*image)->columns; x++)
09954 {
09955 if (IsColorSimilar(*image,q,&target))
09956 q->opacity=(Quantum) atol(matte);
09957 q++;
09958 }
09959 if (SyncAuthenticPixels(*image,exception) == MagickFalse)
09960 break;
09961 }
09962 break;
09963 }
09964 case FloodfillMethod:
09965 case FillToBorderMethod:
09966 {
09967 DrawInfo
09968 *draw_info;
09969
09970 MagickPixelPacket
09971 target;
09972
09973
09974
09975
09976 (void) GetOneVirtualMagickPixel(*image,x_offset,y_offset,&target,
09977 exception);
09978 if (method == FillToBorderMethod)
09979 {
09980 target.red=(MagickRealType)
09981 ScaleShortToQuantum(border_color.red);
09982 target.green=(MagickRealType)
09983 ScaleShortToQuantum(border_color.green);
09984 target.blue=(MagickRealType)
09985 ScaleShortToQuantum(border_color.blue);
09986 }
09987 draw_info=CloneDrawInfo(resource_info->image_info,
09988 (DrawInfo *) NULL);
09989 draw_info->fill.opacity=RoundToQuantum(atof(matte));
09990 (void) FloodfillPaintImage(*image,OpacityChannel,draw_info,&target,
09991 x_offset,y_offset,method == FloodfillMethod ? MagickFalse :
09992 MagickTrue);
09993 draw_info=DestroyDrawInfo(draw_info);
09994 break;
09995 }
09996 case ResetMethod:
09997 {
09998
09999
10000
10001 if (SetImageStorageClass(*image,DirectClass) == MagickFalse)
10002 return(MagickFalse);
10003 for (y=0; y < (long) (*image)->rows; y++)
10004 {
10005 q=QueueAuthenticPixels(*image,0,y,(*image)->columns,1,exception);
10006 if (q == (PixelPacket *) NULL)
10007 break;
10008 for (x=0; x < (int) (*image)->columns; x++)
10009 {
10010 q->opacity=(Quantum) atol(matte);
10011 q++;
10012 }
10013 if (SyncAuthenticPixels(*image,exception) == MagickFalse)
10014 break;
10015 }
10016 if (atol(matte) == OpaqueOpacity)
10017 (*image)->matte=MagickFalse;
10018 break;
10019 }
10020 }
10021 state&=(~UpdateConfigurationState);
10022 }
10023 } while ((state & ExitState) == 0);
10024 (void) XSelectInput(display,windows->image.id,
10025 windows->image.attributes.event_mask);
10026 XSetCursorState(display,windows,MagickFalse);
10027 (void) XFreeCursor(display,cursor);
10028 return(MagickTrue);
10029 }
10030
10031
10032
10033
10034
10035
10036
10037
10038
10039
10040
10041
10042
10043
10044
10045
10046
10047
10048
10049
10050
10051
10052
10053
10054
10055
10056
10057
10058
10059
10060
10061
10062 static Image *XOpenImage(Display *display,XResourceInfo *resource_info,
10063 XWindows *windows,const MagickBooleanType command)
10064 {
10065 const MagickInfo
10066 *magick_info;
10067
10068 ExceptionInfo
10069 *exception;
10070
10071 Image
10072 *nexus;
10073
10074 ImageInfo
10075 *image_info;
10076
10077 static char
10078 filename[MaxTextExtent] = "\0";
10079
10080
10081
10082
10083 if (command == MagickFalse)
10084 XFileBrowserWidget(display,windows,"Open",filename);
10085 else
10086 {
10087 char
10088 **filelist,
10089 **files;
10090
10091 int
10092 count,
10093 status;
10094
10095 register int
10096 i,
10097 j;
10098
10099
10100
10101
10102 status=XGetCommand(display,windows->image.id,&files,&count);
10103 if (status == 0)
10104 {
10105 ThrowXWindowFatalException(XServerError,"UnableToGetProperty","...");
10106 return((Image *) NULL);
10107 }
10108 filelist=(char **) AcquireQuantumMemory((size_t) count,sizeof(*filelist));
10109 if (filelist == (char **) NULL)
10110 {
10111 ThrowXWindowFatalException(ResourceLimitError,
10112 "MemoryAllocationFailed","...");
10113 (void) XFreeStringList(files);
10114 return((Image *) NULL);
10115 }
10116 j=0;
10117 for (i=1; i < count; i++)
10118 if (*files[i] != '-')
10119 filelist[j++]=files[i];
10120 filelist[j]=(char *) NULL;
10121 XListBrowserWidget(display,windows,&windows->widget,
10122 (const char **) filelist,"Load","Select Image to Load:",filename);
10123 filelist=(char **) RelinquishMagickMemory(filelist);
10124 (void) XFreeStringList(files);
10125 }
10126 if (*filename == '\0')
10127 return((Image *) NULL);
10128 image_info=CloneImageInfo(resource_info->image_info);
10129 (void) SetImageInfoProgressMonitor(image_info,(MagickProgressMonitor) NULL,
10130 (void *) NULL);
10131 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
10132 exception=AcquireExceptionInfo();
10133 (void) SetImageInfo(image_info,MagickFalse,exception);
10134 if (LocaleCompare(image_info->magick,"X") == 0)
10135 {
10136 char
10137 seconds[MaxTextExtent];
10138
10139
10140
10141
10142 (void) CopyMagickString(seconds,"0",MaxTextExtent);
10143 (void) XDialogWidget(display,windows,"Grab","Enter any delay in seconds:",
10144 seconds);
10145 if (*seconds == '\0')
10146 return((Image *) NULL);
10147 XDelay(display,(unsigned long) (1000*atol(seconds)));
10148 }
10149 magick_info=GetMagickInfo(image_info->magick,exception);
10150 if ((magick_info != (const MagickInfo *) NULL) &&
10151 (magick_info->raw != MagickFalse))
10152 {
10153 char
10154 geometry[MaxTextExtent];
10155
10156
10157
10158
10159 (void) CopyMagickString(geometry,"512x512",MaxTextExtent);
10160 if (image_info->size != (char *) NULL)
10161 (void) CopyMagickString(geometry,image_info->size,MaxTextExtent);
10162 (void) XDialogWidget(display,windows,"Load","Enter the image geometry:",
10163 geometry);
10164 (void) CloneString(&image_info->size,geometry);
10165 }
10166
10167
10168
10169 XSetCursorState(display,windows,MagickTrue);
10170 XCheckRefreshWindows(display,windows);
10171 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
10172 nexus=ReadImage(image_info,exception);
10173 CatchException(exception);
10174 XSetCursorState(display,windows,MagickFalse);
10175 if (nexus != (Image *) NULL)
10176 XClientMessage(display,windows->image.id,windows->im_protocols,
10177 windows->im_next_image,CurrentTime);
10178 else
10179 {
10180 char
10181 *text,
10182 **textlist;
10183
10184
10185
10186
10187 text=FileToString(filename,~0,exception);
10188 if (text == (char *) NULL)
10189 return((Image *) NULL);
10190 textlist=StringToList(text);
10191 if (textlist != (char **) NULL)
10192 {
10193 char
10194 title[MaxTextExtent];
10195
10196 register int
10197 i;
10198
10199 (void) FormatMagickString(title,MaxTextExtent,
10200 "Unknown format: %s",filename);
10201 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
10202 (const char **) textlist);
10203 for (i=0; textlist[i] != (char *) NULL; i++)
10204 textlist[i]=DestroyString(textlist[i]);
10205 textlist=(char **) RelinquishMagickMemory(textlist);
10206 }
10207 text=DestroyString(text);
10208 }
10209 exception=DestroyExceptionInfo(exception);
10210 image_info=DestroyImageInfo(image_info);
10211 return(nexus);
10212 }
10213
10214
10215
10216
10217
10218
10219
10220
10221
10222
10223
10224
10225
10226
10227
10228
10229
10230
10231
10232
10233
10234
10235
10236
10237
10238
10239
10240
10241
10242 static void XPanImage(Display *display,XWindows *windows,XEvent *event)
10243 {
10244 char
10245 text[MaxTextExtent];
10246
10247 Cursor
10248 cursor;
10249
10250 MagickRealType
10251 x_factor,
10252 y_factor;
10253
10254 RectangleInfo
10255 pan_info;
10256
10257 unsigned long
10258 state;
10259
10260
10261
10262
10263 if ((windows->image.ximage->width > (int) windows->image.width) &&
10264 (windows->image.ximage->height > (int) windows->image.height))
10265 cursor=XCreateFontCursor(display,XC_fleur);
10266 else
10267 if (windows->image.ximage->width > (int) windows->image.width)
10268 cursor=XCreateFontCursor(display,XC_sb_h_double_arrow);
10269 else
10270 if (windows->image.ximage->height > (int) windows->image.height)
10271 cursor=XCreateFontCursor(display,XC_sb_v_double_arrow);
10272 else
10273 cursor=XCreateFontCursor(display,XC_arrow);
10274 (void) XCheckDefineCursor(display,windows->pan.id,cursor);
10275
10276
10277
10278 x_factor=(MagickRealType) windows->image.ximage->width/windows->pan.width;
10279 y_factor=(MagickRealType) windows->image.ximage->height/windows->pan.height;
10280 pan_info.width=windows->pan.width*windows->image.width/
10281 windows->image.ximage->width;
10282 pan_info.height=windows->pan.height*windows->image.height/
10283 windows->image.ximage->height;
10284 pan_info.x=0;
10285 pan_info.y=0;
10286 state=UpdateConfigurationState;
10287 do
10288 {
10289 switch (event->type)
10290 {
10291 case ButtonPress:
10292 {
10293
10294
10295
10296 pan_info.x=event->xbutton.x;
10297 pan_info.y=event->xbutton.y;
10298 state|=UpdateConfigurationState;
10299 break;
10300 }
10301 case ButtonRelease:
10302 {
10303
10304
10305
10306 pan_info.x=event->xbutton.x;
10307 pan_info.y=event->xbutton.y;
10308 state|=UpdateConfigurationState | ExitState;
10309 break;
10310 }
10311 case MotionNotify:
10312 {
10313 pan_info.x=event->xmotion.x;
10314 pan_info.y=event->xmotion.y;
10315 state|=UpdateConfigurationState;
10316 }
10317 default:
10318 break;
10319 }
10320 if ((state & UpdateConfigurationState) != 0)
10321 {
10322
10323
10324
10325 if (pan_info.x < (int) (pan_info.width/2))
10326 pan_info.x=0;
10327 else
10328 pan_info.x=(int) (x_factor*(pan_info.x-(pan_info.width/2)));
10329 if (pan_info.x < 0)
10330 pan_info.x=0;
10331 else
10332 if ((int) (pan_info.x+windows->image.width) >
10333 windows->image.ximage->width)
10334 pan_info.x=(long)
10335 (windows->image.ximage->width-windows->image.width);
10336 if (pan_info.y < (long) (pan_info.height/2))
10337 pan_info.y=0;
10338 else
10339 pan_info.y=(long) (y_factor*(pan_info.y-(pan_info.height/2)));
10340 if (pan_info.y < 0)
10341 pan_info.y=0;
10342 else
10343 if ((int) (pan_info.y+windows->image.height) >
10344 windows->image.ximage->height)
10345 pan_info.y=(long)
10346 (windows->image.ximage->height-windows->image.height);
10347 if ((windows->image.x != (int) pan_info.x) ||
10348 (windows->image.y != (int) pan_info.y))
10349 {
10350
10351
10352
10353 windows->image.x=(int) pan_info.x;
10354 windows->image.y=(int) pan_info.y;
10355 (void) FormatMagickString(text,MaxTextExtent," %ux%u%+d%+d ",
10356 windows->image.width,windows->image.height,windows->image.x,
10357 windows->image.y);
10358 XInfoWidget(display,windows,text);
10359
10360
10361
10362 XDrawPanRectangle(display,windows);
10363 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
10364 }
10365 state&=(~UpdateConfigurationState);
10366 }
10367
10368
10369
10370 if ((state & ExitState) == 0)
10371 XScreenEvent(display,windows,event);
10372 } while ((state & ExitState) == 0);
10373
10374
10375
10376 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
10377 (void) XFreeCursor(display,cursor);
10378 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
10379 }
10380
10381
10382
10383
10384
10385
10386
10387
10388
10389
10390
10391
10392
10393
10394
10395
10396
10397
10398
10399
10400
10401
10402
10403
10404
10405
10406
10407
10408
10409
10410
10411
10412
10413 static MagickBooleanType XPasteImage(Display *display,
10414 XResourceInfo *resource_info,XWindows *windows,Image *image)
10415 {
10416 static const char
10417 *PasteMenu[] =
10418 {
10419 "Operator",
10420 "Help",
10421 "Dismiss",
10422 (char *) NULL
10423 };
10424
10425 static const ModeType
10426 PasteCommands[] =
10427 {
10428 PasteOperatorsCommand,
10429 PasteHelpCommand,
10430 PasteDismissCommand
10431 };
10432
10433 static CompositeOperator
10434 compose = CopyCompositeOp;
10435
10436 char
10437 text[MaxTextExtent];
10438
10439 Cursor
10440 cursor;
10441
10442 Image
10443 *paste_image;
10444
10445 int
10446 entry,
10447 id,
10448 x,
10449 y;
10450
10451 MagickRealType
10452 scale_factor;
10453
10454 RectangleInfo
10455 highlight_info,
10456 paste_info;
10457
10458 unsigned int
10459 height,
10460 width;
10461
10462 unsigned long
10463 state;
10464
10465 XEvent
10466 event;
10467
10468
10469
10470
10471 if (resource_info->copy_image == (Image *) NULL)
10472 return(MagickFalse);
10473 paste_image=CloneImage(resource_info->copy_image,0,0,MagickTrue,
10474 &image->exception);
10475
10476
10477
10478 (void) CloneString(&windows->command.name,"Paste");
10479 windows->command.data=1;
10480 (void) XCommandWidget(display,windows,PasteMenu,(XEvent *) NULL);
10481 (void) XMapRaised(display,windows->command.id);
10482 XClientMessage(display,windows->image.id,windows->im_protocols,
10483 windows->im_update_widget,CurrentTime);
10484
10485
10486
10487 XSetCursorState(display,windows,MagickFalse);
10488 XQueryPosition(display,windows->image.id,&x,&y);
10489 (void) XSelectInput(display,windows->image.id,
10490 windows->image.attributes.event_mask | PointerMotionMask);
10491 paste_info.x=windows->image.x+x;
10492 paste_info.y=windows->image.y+y;
10493 paste_info.width=0;
10494 paste_info.height=0;
10495 cursor=XCreateFontCursor(display,XC_ul_angle);
10496 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
10497 state=DefaultState;
10498 do
10499 {
10500 if (windows->info.mapped != MagickFalse)
10501 {
10502
10503
10504
10505 (void) FormatMagickString(text,MaxTextExtent," %+ld%+ld ",
10506 paste_info.x,paste_info.y);
10507 XInfoWidget(display,windows,text);
10508 }
10509 highlight_info=paste_info;
10510 highlight_info.x=paste_info.x-windows->image.x;
10511 highlight_info.y=paste_info.y-windows->image.y;
10512 XHighlightRectangle(display,windows->image.id,
10513 windows->image.highlight_context,&highlight_info);
10514
10515
10516
10517 XScreenEvent(display,windows,&event);
10518 XHighlightRectangle(display,windows->image.id,
10519 windows->image.highlight_context,&highlight_info);
10520 if (event.xany.window == windows->command.id)
10521 {
10522
10523
10524
10525 id=XCommandWidget(display,windows,PasteMenu,&event);
10526 if (id < 0)
10527 continue;
10528 switch (PasteCommands[id])
10529 {
10530 case PasteOperatorsCommand:
10531 {
10532 char
10533 command[MaxTextExtent],
10534 **operators;
10535
10536
10537
10538
10539 operators=GetMagickOptions(MagickComposeOptions);
10540 if (operators == (char **) NULL)
10541 break;
10542 entry=XMenuWidget(display,windows,PasteMenu[id],
10543 (const char **) operators,command);
10544 if (entry >= 0)
10545 compose=(CompositeOperator) ParseMagickOption(
10546 MagickComposeOptions,MagickFalse,operators[entry]);
10547 operators=DestroyStringList(operators);
10548 break;
10549 }
10550 case PasteHelpCommand:
10551 {
10552 XTextViewWidget(display,resource_info,windows,MagickFalse,
10553 "Help Viewer - Image Composite",ImagePasteHelp);
10554 break;
10555 }
10556 case PasteDismissCommand:
10557 {
10558
10559
10560
10561 state|=EscapeState;
10562 state|=ExitState;
10563 break;
10564 }
10565 default:
10566 break;
10567 }
10568 continue;
10569 }
10570 switch (event.type)
10571 {
10572 case ButtonPress:
10573 {
10574 if (image->debug != MagickFalse)
10575 (void) LogMagickEvent(X11Event,GetMagickModule(),
10576 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
10577 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10578 if (event.xbutton.button != Button1)
10579 break;
10580 if (event.xbutton.window != windows->image.id)
10581 break;
10582
10583
10584
10585 width=(unsigned int) image->columns;
10586 height=(unsigned int) image->rows;
10587 x=0;
10588 y=0;
10589 if (windows->image.crop_geometry != (char *) NULL)
10590 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
10591 &width,&height);
10592 scale_factor=(MagickRealType) windows->image.ximage->width/width;
10593 paste_info.width=(unsigned int) (scale_factor*paste_image->columns+0.5);
10594 scale_factor=(MagickRealType) windows->image.ximage->height/height;
10595 paste_info.height=(unsigned int) (scale_factor*paste_image->rows+0.5);
10596 (void) XCheckDefineCursor(display,windows->image.id,cursor);
10597 paste_info.x=windows->image.x+event.xbutton.x;
10598 paste_info.y=windows->image.y+event.xbutton.y;
10599 break;
10600 }
10601 case ButtonRelease:
10602 {
10603 if (image->debug != MagickFalse)
10604 (void) LogMagickEvent(X11Event,GetMagickModule(),
10605 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
10606 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10607 if (event.xbutton.button != Button1)
10608 break;
10609 if (event.xbutton.window != windows->image.id)
10610 break;
10611 if ((paste_info.width != 0) && (paste_info.height != 0))
10612 {
10613
10614
10615
10616 paste_info.x=windows->image.x+event.xbutton.x;
10617 paste_info.y=windows->image.y+event.xbutton.y;
10618 state|=ExitState;
10619 }
10620 break;
10621 }
10622 case Expose:
10623 break;
10624 case KeyPress:
10625 {
10626 char
10627 command[MaxTextExtent];
10628
10629 KeySym
10630 key_symbol;
10631
10632 int
10633 length;
10634
10635 if (event.xkey.window != windows->image.id)
10636 break;
10637
10638
10639
10640 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
10641 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
10642 *(command+length)='\0';
10643 if (image->debug != MagickFalse)
10644 (void) LogMagickEvent(X11Event,GetMagickModule(),
10645 "Key press: 0x%lx (%s)",(long) key_symbol,command);
10646 switch ((int) key_symbol)
10647 {
10648 case XK_Escape:
10649 case XK_F20:
10650 {
10651
10652
10653
10654 paste_image=DestroyImage(paste_image);
10655 state|=EscapeState;
10656 state|=ExitState;
10657 break;
10658 }
10659 case XK_F1:
10660 case XK_Help:
10661 {
10662 (void) XSetFunction(display,windows->image.highlight_context,
10663 GXcopy);
10664 XTextViewWidget(display,resource_info,windows,MagickFalse,
10665 "Help Viewer - Image Composite",ImagePasteHelp);
10666 (void) XSetFunction(display,windows->image.highlight_context,
10667 GXinvert);
10668 break;
10669 }
10670 default:
10671 {
10672 (void) XBell(display,0);
10673 break;
10674 }
10675 }
10676 break;
10677 }
10678 case MotionNotify:
10679 {
10680
10681
10682
10683 x=event.xmotion.x;
10684 y=event.xmotion.y;
10685 if (windows->info.mapped != MagickFalse)
10686 {
10687 if ((x < (int) (windows->info.x+windows->info.width)) &&
10688 (y < (int) (windows->info.y+windows->info.height)))
10689 (void) XWithdrawWindow(display,windows->info.id,
10690 windows->info.screen);
10691 }
10692 else
10693 if ((x > (int) (windows->info.x+windows->info.width)) ||
10694 (y > (int) (windows->info.y+windows->info.height)))
10695 (void) XMapWindow(display,windows->info.id);
10696 paste_info.x=windows->image.x+x;
10697 paste_info.y=windows->image.y+y;
10698 break;
10699 }
10700 default:
10701 {
10702 if (image->debug != MagickFalse)
10703 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
10704 event.type);
10705 break;
10706 }
10707 }
10708 } while ((state & ExitState) == 0);
10709 (void) XSelectInput(display,windows->image.id,
10710 windows->image.attributes.event_mask);
10711 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
10712 XSetCursorState(display,windows,MagickFalse);
10713 (void) XFreeCursor(display,cursor);
10714 if ((state & EscapeState) != 0)
10715 return(MagickTrue);
10716
10717
10718
10719 XSetCursorState(display,windows,MagickTrue);
10720 XCheckRefreshWindows(display,windows);
10721 width=(unsigned int) image->columns;
10722 height=(unsigned int) image->rows;
10723 x=0;
10724 y=0;
10725 if (windows->image.crop_geometry != (char *) NULL)
10726 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
10727 scale_factor=(MagickRealType) width/windows->image.ximage->width;
10728 paste_info.x+=x;
10729 paste_info.x=(int) (scale_factor*paste_info.x+0.5);
10730 paste_info.width=(unsigned int) (scale_factor*paste_info.width+0.5);
10731 scale_factor=(MagickRealType) height/windows->image.ximage->height;
10732 paste_info.y+=y;
10733 paste_info.y=(int) (scale_factor*paste_info.y*scale_factor+0.5);
10734 paste_info.height=(unsigned int) (scale_factor*paste_info.height+0.5);
10735
10736
10737
10738 (void) CompositeImage(image,compose,paste_image,paste_info.x,paste_info.y);
10739 paste_image=DestroyImage(paste_image);
10740 XSetCursorState(display,windows,MagickFalse);
10741
10742
10743
10744 XConfigureImageColormap(display,resource_info,windows,image);
10745 (void) XConfigureImage(display,resource_info,windows,image);
10746 return(MagickTrue);
10747 }
10748
10749
10750
10751
10752
10753
10754
10755
10756
10757
10758
10759
10760
10761
10762
10763
10764
10765
10766
10767
10768
10769
10770
10771
10772
10773
10774
10775
10776
10777
10778
10779
10780 static MagickBooleanType XPrintImage(Display *display,
10781 XResourceInfo *resource_info,XWindows *windows,Image *image)
10782 {
10783 char
10784 filename[MaxTextExtent],
10785 geometry[MaxTextExtent];
10786
10787 Image
10788 *print_image;
10789
10790 ImageInfo
10791 *image_info;
10792
10793 MagickStatusType
10794 status;
10795
10796
10797
10798
10799 image_info=CloneImageInfo(resource_info->image_info);
10800 (void) FormatMagickString(geometry,MaxTextExtent,"Letter");
10801 if (image_info->page != (char *) NULL)
10802 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
10803 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
10804 "Select Postscript Page Geometry:",geometry);
10805 if (*geometry == '\0')
10806 return(MagickTrue);
10807 image_info->page=GetPageGeometry(geometry);
10808
10809
10810
10811 XSetCursorState(display,windows,MagickTrue);
10812 XCheckRefreshWindows(display,windows);
10813 print_image=CloneImage(image,0,0,MagickTrue,&image->exception);
10814 if (print_image == (Image *) NULL)
10815 return(MagickFalse);
10816 (void) FormatMagickString(geometry,MaxTextExtent,"%dx%d!",
10817 windows->image.ximage->width,windows->image.ximage->height);
10818 (void) TransformImage(&print_image,windows->image.crop_geometry,geometry);
10819
10820
10821
10822 (void) AcquireUniqueFilename(filename);
10823 (void) FormatMagickString(print_image->filename,MaxTextExtent,"print:%s",
10824 filename);
10825 status=WriteImage(image_info,print_image);
10826 (void) RelinquishUniqueFileResource(filename);
10827 print_image=DestroyImage(print_image);
10828 image_info=DestroyImageInfo(image_info);
10829 XSetCursorState(display,windows,MagickFalse);
10830 return(status != 0 ? MagickTrue : MagickFalse);
10831 }
10832
10833
10834
10835
10836
10837
10838
10839
10840
10841
10842
10843
10844
10845
10846
10847
10848
10849
10850
10851
10852
10853
10854
10855
10856
10857
10858
10859
10860
10861
10862
10863
10864 static MagickBooleanType XROIImage(Display *display,
10865 XResourceInfo *resource_info,XWindows *windows,Image **image)
10866 {
10867 #define ApplyMenus 7
10868
10869 static const char
10870 *ROIMenu[] =
10871 {
10872 "Help",
10873 "Dismiss",
10874 (char *) NULL
10875 },
10876 *ApplyMenu[] =
10877 {
10878 "File",
10879 "Edit",
10880 "Transform",
10881 "Enhance",
10882 "Effects",
10883 "F/X",
10884 "Miscellany",
10885 "Help",
10886 "Dismiss",
10887 (char *) NULL
10888 },
10889 *FileMenu[] =
10890 {
10891 "Save...",
10892 "Print...",
10893 (char *) NULL
10894 },
10895 *EditMenu[] =
10896 {
10897 "Undo",
10898 "Redo",
10899 (char *) NULL
10900 },
10901 *TransformMenu[] =
10902 {
10903 "Flop",
10904 "Flip",
10905 "Rotate Right",
10906 "Rotate Left",
10907 (char *) NULL
10908 },
10909 *EnhanceMenu[] =
10910 {
10911 "Hue...",
10912 "Saturation...",
10913 "Brightness...",
10914 "Gamma...",
10915 "Spiff",
10916 "Dull",
10917 "Contrast Stretch...",
10918 "Sigmoidal Contrast...",
10919 "Normalize",
10920 "Equalize",
10921 "Negate",
10922 "Grayscale",
10923 "Map...",
10924 "Quantize...",
10925 (char *) NULL
10926 },
10927 *EffectsMenu[] =
10928 {
10929 "Despeckle",
10930 "Emboss",
10931 "Reduce Noise",
10932 "Add Noise",
10933 "Sharpen...",
10934 "Blur...",
10935 "Threshold...",
10936 "Edge Detect...",
10937 "Spread...",
10938 "Shade...",
10939 "Raise...",
10940 "Segment...",
10941 (char *) NULL
10942 },
10943 *FXMenu[] =
10944 {
10945 "Solarize...",
10946 "Sepia Tone...",
10947 "Swirl...",
10948 "Implode...",
10949 "Vignette...",
10950 "Wave...",
10951 "Oil Paint...",
10952 "Charcoal Draw...",
10953 (char *) NULL
10954 },
10955 *MiscellanyMenu[] =
10956 {
10957 "Image Info",
10958 "Zoom Image",
10959 "Show Preview...",
10960 "Show Histogram",
10961 "Show Matte",
10962 (char *) NULL
10963 };
10964
10965 static const char
10966 **Menus[ApplyMenus] =
10967 {
10968 FileMenu,
10969 EditMenu,
10970 TransformMenu,
10971 EnhanceMenu,
10972 EffectsMenu,
10973 FXMenu,
10974 MiscellanyMenu
10975 };
10976
10977 static const CommandType
10978 ApplyCommands[] =
10979 {
10980 NullCommand,
10981 NullCommand,
10982 NullCommand,
10983 NullCommand,
10984 NullCommand,
10985 NullCommand,
10986 NullCommand,
10987 HelpCommand,
10988 QuitCommand
10989 },
10990 FileCommands[] =
10991 {
10992 SaveCommand,
10993 PrintCommand
10994 },
10995 EditCommands[] =
10996 {
10997 UndoCommand,
10998 RedoCommand
10999 },
11000 TransformCommands[] =
11001 {
11002 FlopCommand,
11003 FlipCommand,
11004 RotateRightCommand,
11005 RotateLeftCommand
11006 },
11007 EnhanceCommands[] =
11008 {
11009 HueCommand,
11010 SaturationCommand,
11011 BrightnessCommand,
11012 GammaCommand,
11013 SpiffCommand,
11014 DullCommand,
11015 ContrastStretchCommand,
11016 SigmoidalContrastCommand,
11017 NormalizeCommand,
11018 EqualizeCommand,
11019 NegateCommand,
11020 GrayscaleCommand,
11021 MapCommand,
11022 QuantizeCommand
11023 },
11024 EffectsCommands[] =
11025 {
11026 DespeckleCommand,
11027 EmbossCommand,
11028 ReduceNoiseCommand,
11029 AddNoiseCommand,
11030 SharpenCommand,
11031 BlurCommand,
11032 EdgeDetectCommand,
11033 SpreadCommand,
11034 ShadeCommand,
11035 RaiseCommand,
11036 SegmentCommand
11037 },
11038 FXCommands[] =
11039 {
11040 SolarizeCommand,
11041 SepiaToneCommand,
11042 SwirlCommand,
11043 ImplodeCommand,
11044 VignetteCommand,
11045 WaveCommand,
11046 OilPaintCommand,
11047 CharcoalDrawCommand
11048 },
11049 MiscellanyCommands[] =
11050 {
11051 InfoCommand,
11052 ZoomCommand,
11053 ShowPreviewCommand,
11054 ShowHistogramCommand,
11055 ShowMatteCommand
11056 },
11057 ROICommands[] =
11058 {
11059 ROIHelpCommand,
11060 ROIDismissCommand
11061 };
11062
11063 static const CommandType
11064 *Commands[ApplyMenus] =
11065 {
11066 FileCommands,
11067 EditCommands,
11068 TransformCommands,
11069 EnhanceCommands,
11070 EffectsCommands,
11071 FXCommands,
11072 MiscellanyCommands
11073 };
11074
11075 char
11076 command[MaxTextExtent],
11077 text[MaxTextExtent];
11078
11079 CommandType
11080 command_type;
11081
11082 Cursor
11083 cursor;
11084
11085 Image
11086 *roi_image;
11087
11088 int
11089 entry,
11090 id,
11091 x,
11092 y;
11093
11094 MagickRealType
11095 scale_factor;
11096
11097 MagickProgressMonitor
11098 progress_monitor;
11099
11100 RectangleInfo
11101 crop_info,
11102 highlight_info,
11103 roi_info;
11104
11105 unsigned int
11106 height,
11107 width;
11108
11109 unsigned long
11110 state;
11111
11112 XEvent
11113 event;
11114
11115
11116
11117
11118 (void) CloneString(&windows->command.name,"ROI");
11119 windows->command.data=0;
11120 (void) XCommandWidget(display,windows,ROIMenu,(XEvent *) NULL);
11121 (void) XMapRaised(display,windows->command.id);
11122 XClientMessage(display,windows->image.id,windows->im_protocols,
11123 windows->im_update_widget,CurrentTime);
11124
11125
11126
11127 XQueryPosition(display,windows->image.id,&x,&y);
11128 (void) XSelectInput(display,windows->image.id,
11129 windows->image.attributes.event_mask | PointerMotionMask);
11130 roi_info.x=windows->image.x+x;
11131 roi_info.y=windows->image.y+y;
11132 roi_info.width=0;
11133 roi_info.height=0;
11134 cursor=XCreateFontCursor(display,XC_fleur);
11135 state=DefaultState;
11136 do
11137 {
11138 if (windows->info.mapped != MagickFalse)
11139 {
11140
11141
11142
11143 (void) FormatMagickString(text,MaxTextExtent," %+ld%+ld ",
11144 roi_info.x,roi_info.y);
11145 XInfoWidget(display,windows,text);
11146 }
11147
11148
11149
11150 XScreenEvent(display,windows,&event);
11151 if (event.xany.window == windows->command.id)
11152 {
11153
11154
11155
11156 id=XCommandWidget(display,windows,ROIMenu,&event);
11157 if (id < 0)
11158 continue;
11159 switch (ROICommands[id])
11160 {
11161 case ROIHelpCommand:
11162 {
11163 XTextViewWidget(display,resource_info,windows,MagickFalse,
11164 "Help Viewer - Region of Interest",ImageROIHelp);
11165 break;
11166 }
11167 case ROIDismissCommand:
11168 {
11169
11170
11171
11172 state|=EscapeState;
11173 state|=ExitState;
11174 break;
11175 }
11176 default:
11177 break;
11178 }
11179 continue;
11180 }
11181 switch (event.type)
11182 {
11183 case ButtonPress:
11184 {
11185 if (event.xbutton.button != Button1)
11186 break;
11187 if (event.xbutton.window != windows->image.id)
11188 break;
11189
11190
11191
11192 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11193 roi_info.x=windows->image.x+event.xbutton.x;
11194 roi_info.y=windows->image.y+event.xbutton.y;
11195 state|=ExitState;
11196 break;
11197 }
11198 case ButtonRelease:
11199 break;
11200 case Expose:
11201 break;
11202 case KeyPress:
11203 {
11204 KeySym
11205 key_symbol;
11206
11207 if (event.xkey.window != windows->image.id)
11208 break;
11209
11210
11211
11212 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11213 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11214 switch ((int) key_symbol)
11215 {
11216 case XK_Escape:
11217 case XK_F20:
11218 {
11219
11220
11221
11222 state|=EscapeState;
11223 state|=ExitState;
11224 break;
11225 }
11226 case XK_F1:
11227 case XK_Help:
11228 {
11229 XTextViewWidget(display,resource_info,windows,MagickFalse,
11230 "Help Viewer - Region of Interest",ImageROIHelp);
11231 break;
11232 }
11233 default:
11234 {
11235 (void) XBell(display,0);
11236 break;
11237 }
11238 }
11239 break;
11240 }
11241 case MotionNotify:
11242 {
11243
11244
11245
11246 x=event.xmotion.x;
11247 y=event.xmotion.y;
11248 if (windows->info.mapped != MagickFalse)
11249 {
11250 if ((x < (int) (windows->info.x+windows->info.width)) &&
11251 (y < (int) (windows->info.y+windows->info.height)))
11252 (void) XWithdrawWindow(display,windows->info.id,
11253 windows->info.screen);
11254 }
11255 else
11256 if ((x > (int) (windows->info.x+windows->info.width)) ||
11257 (y > (int) (windows->info.y+windows->info.height)))
11258 (void) XMapWindow(display,windows->info.id);
11259 roi_info.x=windows->image.x+x;
11260 roi_info.y=windows->image.y+y;
11261 break;
11262 }
11263 default:
11264 break;
11265 }
11266 } while ((state & ExitState) == 0);
11267 (void) XSelectInput(display,windows->image.id,
11268 windows->image.attributes.event_mask);
11269 if ((state & EscapeState) != 0)
11270 {
11271
11272
11273
11274 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11275 (void) XFreeCursor(display,cursor);
11276 return(MagickTrue);
11277 }
11278 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
11279 do
11280 {
11281
11282
11283
11284 x=(int) roi_info.x;
11285 y=(int) roi_info.y;
11286 roi_info.width=0;
11287 roi_info.height=0;
11288 state=DefaultState;
11289 do
11290 {
11291 highlight_info=roi_info;
11292 highlight_info.x=roi_info.x-windows->image.x;
11293 highlight_info.y=roi_info.y-windows->image.y;
11294 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11295 {
11296
11297
11298
11299 if (windows->info.mapped == MagickFalse)
11300 (void) XMapWindow(display,windows->info.id);
11301 (void) FormatMagickString(text,MaxTextExtent," %lux%lu%+ld%+ld",
11302 roi_info.width,roi_info.height,roi_info.x,roi_info.y);
11303 XInfoWidget(display,windows,text);
11304 XHighlightRectangle(display,windows->image.id,
11305 windows->image.highlight_context,&highlight_info);
11306 }
11307 else
11308 if (windows->info.mapped != MagickFalse)
11309 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11310
11311
11312
11313 XScreenEvent(display,windows,&event);
11314 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11315 XHighlightRectangle(display,windows->image.id,
11316 windows->image.highlight_context,&highlight_info);
11317 switch (event.type)
11318 {
11319 case ButtonPress:
11320 {
11321 roi_info.x=windows->image.x+event.xbutton.x;
11322 roi_info.y=windows->image.y+event.xbutton.y;
11323 break;
11324 }
11325 case ButtonRelease:
11326 {
11327
11328
11329
11330 roi_info.x=windows->image.x+event.xbutton.x;
11331 roi_info.y=windows->image.y+event.xbutton.y;
11332 XSetCursorState(display,windows,MagickFalse);
11333 state|=ExitState;
11334 if (LocaleCompare(windows->command.name,"Apply") == 0)
11335 break;
11336 (void) CloneString(&windows->command.name,"Apply");
11337 windows->command.data=ApplyMenus;
11338 (void) XCommandWidget(display,windows,ApplyMenu,(XEvent *) NULL);
11339 break;
11340 }
11341 case Expose:
11342 break;
11343 case MotionNotify:
11344 {
11345 roi_info.x=windows->image.x+event.xmotion.x;
11346 roi_info.y=windows->image.y+event.xmotion.y;
11347 }
11348 default:
11349 break;
11350 }
11351 if ((((int) roi_info.x != x) && ((int) roi_info.y != y)) ||
11352 ((state & ExitState) != 0))
11353 {
11354
11355
11356
11357 if (roi_info.x < 0)
11358 roi_info.x=0;
11359 else
11360 if (roi_info.x > (int) windows->image.ximage->width)
11361 roi_info.x=windows->image.ximage->width;
11362 if ((int) roi_info.x < x)
11363 roi_info.width=(unsigned int) (x-roi_info.x);
11364 else
11365 {
11366 roi_info.width=(unsigned int) (roi_info.x-x);
11367 roi_info.x=x;
11368 }
11369 if (roi_info.y < 0)
11370 roi_info.y=0;
11371 else
11372 if (roi_info.y > (int) windows->image.ximage->height)
11373 roi_info.y=windows->image.ximage->height;
11374 if ((int) roi_info.y < y)
11375 roi_info.height=(unsigned int) (y-roi_info.y);
11376 else
11377 {
11378 roi_info.height=(unsigned int) (roi_info.y-y);
11379 roi_info.y=y;
11380 }
11381 }
11382 } while ((state & ExitState) == 0);
11383
11384
11385
11386 state=DefaultState;
11387 command_type=NullCommand;
11388 (void) XMapWindow(display,windows->info.id);
11389 do
11390 {
11391 if (windows->info.mapped != MagickFalse)
11392 {
11393
11394
11395
11396 (void) FormatMagickString(text,MaxTextExtent," %lux%lu%+ld%+ld",
11397 roi_info.width,roi_info.height,roi_info.x,roi_info.y);
11398 XInfoWidget(display,windows,text);
11399 }
11400 highlight_info=roi_info;
11401 highlight_info.x=roi_info.x-windows->image.x;
11402 highlight_info.y=roi_info.y-windows->image.y;
11403 if ((highlight_info.width <= 3) || (highlight_info.height <= 3))
11404 {
11405 state|=EscapeState;
11406 state|=ExitState;
11407 break;
11408 }
11409 if ((state & UpdateRegionState) != 0)
11410 {
11411 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11412 switch (command_type)
11413 {
11414 case UndoCommand:
11415 case RedoCommand:
11416 {
11417 (void) XMagickCommand(display,resource_info,windows,command_type,
11418 image);
11419 break;
11420 }
11421 default:
11422 {
11423
11424
11425
11426 progress_monitor=SetImageProgressMonitor(*image,
11427 (MagickProgressMonitor) NULL,(*image)->client_data);
11428 crop_info=roi_info;
11429 width=(unsigned int) (*image)->columns;
11430 height=(unsigned int) (*image)->rows;
11431 x=0;
11432 y=0;
11433 if (windows->image.crop_geometry != (char *) NULL)
11434 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
11435 &width,&height);
11436 scale_factor=(MagickRealType) width/windows->image.ximage->width;
11437 crop_info.x+=x;
11438 crop_info.x=(int) (scale_factor*crop_info.x+0.5);
11439 crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5);
11440 scale_factor=(MagickRealType)
11441 height/windows->image.ximage->height;
11442 crop_info.y+=y;
11443 crop_info.y=(int) (scale_factor*crop_info.y+0.5);
11444 crop_info.height=(unsigned int)
11445 (scale_factor*crop_info.height+0.5);
11446 roi_image=CropImage(*image,&crop_info,&(*image)->exception);
11447 (void) SetImageProgressMonitor(*image,progress_monitor,
11448 (*image)->client_data);
11449 if (roi_image == (Image *) NULL)
11450 continue;
11451
11452
11453
11454 windows->image.orphan=MagickTrue;
11455 (void) XMagickCommand(display,resource_info,windows,command_type,
11456 &roi_image);
11457 progress_monitor=SetImageProgressMonitor(*image,
11458 (MagickProgressMonitor) NULL,(*image)->client_data);
11459 (void) XMagickCommand(display,resource_info,windows,
11460 SaveToUndoBufferCommand,image);
11461 windows->image.orphan=MagickFalse;
11462 (void) CompositeImage(*image,CopyCompositeOp,roi_image,
11463 crop_info.x,crop_info.y);
11464 roi_image=DestroyImage(roi_image);
11465 (void) SetImageProgressMonitor(*image,progress_monitor,
11466 (*image)->client_data);
11467 break;
11468 }
11469 }
11470 if (command_type != InfoCommand)
11471 {
11472 XConfigureImageColormap(display,resource_info,windows,*image);
11473 (void) XConfigureImage(display,resource_info,windows,*image);
11474 }
11475 XCheckRefreshWindows(display,windows);
11476 XInfoWidget(display,windows,text);
11477 (void) XSetFunction(display,windows->image.highlight_context,
11478 GXinvert);
11479 state&=(~UpdateRegionState);
11480 }
11481 XHighlightRectangle(display,windows->image.id,
11482 windows->image.highlight_context,&highlight_info);
11483 XScreenEvent(display,windows,&event);
11484 if (event.xany.window == windows->command.id)
11485 {
11486
11487
11488
11489 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11490 command_type=NullCommand;
11491 id=XCommandWidget(display,windows,ApplyMenu,&event);
11492 if (id >= 0)
11493 {
11494 (void) CopyMagickString(command,ApplyMenu[id],MaxTextExtent);
11495 command_type=ApplyCommands[id];
11496 if (id < ApplyMenus)
11497 {
11498
11499
11500
11501 entry=XMenuWidget(display,windows,ApplyMenu[id],
11502 (const char **) Menus[id],command);
11503 if (entry >= 0)
11504 {
11505 (void) CopyMagickString(command,Menus[id][entry],
11506 MaxTextExtent);
11507 command_type=Commands[id][entry];
11508 }
11509 }
11510 }
11511 (void) XSetFunction(display,windows->image.highlight_context,
11512 GXinvert);
11513 XHighlightRectangle(display,windows->image.id,
11514 windows->image.highlight_context,&highlight_info);
11515 if (command_type == HelpCommand)
11516 {
11517 (void) XSetFunction(display,windows->image.highlight_context,
11518 GXcopy);
11519 XTextViewWidget(display,resource_info,windows,MagickFalse,
11520 "Help Viewer - Region of Interest",ImageROIHelp);
11521 (void) XSetFunction(display,windows->image.highlight_context,
11522 GXinvert);
11523 continue;
11524 }
11525 if (command_type == QuitCommand)
11526 {
11527
11528
11529
11530 state|=EscapeState;
11531 state|=ExitState;
11532 continue;
11533 }
11534 if (command_type != NullCommand)
11535 state|=UpdateRegionState;
11536 continue;
11537 }
11538 XHighlightRectangle(display,windows->image.id,
11539 windows->image.highlight_context,&highlight_info);
11540 switch (event.type)
11541 {
11542 case ButtonPress:
11543 {
11544 x=windows->image.x;
11545 y=windows->image.y;
11546 if (event.xbutton.button != Button1)
11547 break;
11548 if (event.xbutton.window != windows->image.id)
11549 break;
11550 x=windows->image.x+event.xbutton.x;
11551 y=windows->image.y+event.xbutton.y;
11552 if ((x < (int) (roi_info.x+RoiDelta)) &&
11553 (x > (int) (roi_info.x-RoiDelta)) &&
11554 (y < (int) (roi_info.y+RoiDelta)) &&
11555 (y > (int) (roi_info.y-RoiDelta)))
11556 {
11557 roi_info.x=(long) (roi_info.x+roi_info.width);
11558 roi_info.y=(long) (roi_info.y+roi_info.height);
11559 state|=UpdateConfigurationState;
11560 break;
11561 }
11562 if ((x < (int) (roi_info.x+RoiDelta)) &&
11563 (x > (int) (roi_info.x-RoiDelta)) &&
11564 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11565 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11566 {
11567 roi_info.x=(long) (roi_info.x+roi_info.width);
11568 state|=UpdateConfigurationState;
11569 break;
11570 }
11571 if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) &&
11572 (x > (int) (roi_info.x+roi_info.width-RoiDelta)) &&
11573 (y < (int) (roi_info.y+RoiDelta)) &&
11574 (y > (int) (roi_info.y-RoiDelta)))
11575 {
11576 roi_info.y=(long) (roi_info.y+roi_info.height);
11577 state|=UpdateConfigurationState;
11578 break;
11579 }
11580 if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) &&
11581 (x > (int) (roi_info.x+roi_info.width-RoiDelta)) &&
11582 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11583 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11584 {
11585 state|=UpdateConfigurationState;
11586 break;
11587 }
11588 }
11589 case ButtonRelease:
11590 {
11591 if (event.xbutton.window == windows->pan.id)
11592 if ((highlight_info.x != crop_info.x-windows->image.x) ||
11593 (highlight_info.y != crop_info.y-windows->image.y))
11594 XHighlightRectangle(display,windows->image.id,
11595 windows->image.highlight_context,&highlight_info);
11596 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11597 event.xbutton.time);
11598 break;
11599 }
11600 case Expose:
11601 {
11602 if (event.xexpose.window == windows->image.id)
11603 if (event.xexpose.count == 0)
11604 {
11605 event.xexpose.x=(int) highlight_info.x;
11606 event.xexpose.y=(int) highlight_info.y;
11607 event.xexpose.width=(int) highlight_info.width;
11608 event.xexpose.height=(int) highlight_info.height;
11609 XRefreshWindow(display,&windows->image,&event);
11610 }
11611 if (event.xexpose.window == windows->info.id)
11612 if (event.xexpose.count == 0)
11613 XInfoWidget(display,windows,text);
11614 break;
11615 }
11616 case KeyPress:
11617 {
11618 KeySym
11619 key_symbol;
11620
11621 if (event.xkey.window != windows->image.id)
11622 break;
11623
11624
11625
11626 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11627 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11628 switch ((int) key_symbol)
11629 {
11630 case XK_Shift_L:
11631 case XK_Shift_R:
11632 break;
11633 case XK_Escape:
11634 case XK_F20:
11635 state|=EscapeState;
11636 case XK_Return:
11637 {
11638 state|=ExitState;
11639 break;
11640 }
11641 case XK_Home:
11642 case XK_KP_Home:
11643 {
11644 roi_info.x=(long) (windows->image.width/2L-roi_info.width/2L);
11645 roi_info.y=(long) (windows->image.height/2L-roi_info.height/2L);
11646 break;
11647 }
11648 case XK_Left:
11649 case XK_KP_Left:
11650 {
11651 roi_info.x--;
11652 break;
11653 }
11654 case XK_Up:
11655 case XK_KP_Up:
11656 case XK_Next:
11657 {
11658 roi_info.y--;
11659 break;
11660 }
11661 case XK_Right:
11662 case XK_KP_Right:
11663 {
11664 roi_info.x++;
11665 break;
11666 }
11667 case XK_Prior:
11668 case XK_Down:
11669 case XK_KP_Down:
11670 {
11671 roi_info.y++;
11672 break;
11673 }
11674 case XK_F1:
11675 case XK_Help:
11676 {
11677 (void) XSetFunction(display,windows->image.highlight_context,
11678 GXcopy);
11679 XTextViewWidget(display,resource_info,windows,MagickFalse,
11680 "Help Viewer - Region of Interest",ImageROIHelp);
11681 (void) XSetFunction(display,windows->image.highlight_context,
11682 GXinvert);
11683 break;
11684 }
11685 default:
11686 {
11687 command_type=XImageWindowCommand(display,resource_info,windows,
11688 event.xkey.state,key_symbol,image);
11689 if (command_type != NullCommand)
11690 state|=UpdateRegionState;
11691 break;
11692 }
11693 }
11694 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11695 event.xkey.time);
11696 break;
11697 }
11698 case KeyRelease:
11699 break;
11700 case MotionNotify:
11701 {
11702 if (event.xbutton.window != windows->image.id)
11703 break;
11704
11705
11706
11707 x=event.xmotion.x;
11708 y=event.xmotion.y;
11709 if (windows->info.mapped != MagickFalse)
11710 {
11711 if ((x < (int) (windows->info.x+windows->info.width)) &&
11712 (y < (int) (windows->info.y+windows->info.height)))
11713 (void) XWithdrawWindow(display,windows->info.id,
11714 windows->info.screen);
11715 }
11716 else
11717 if ((x > (int) (windows->info.x+windows->info.width)) ||
11718 (y > (int) (windows->info.y+windows->info.height)))
11719 (void) XMapWindow(display,windows->info.id);
11720 roi_info.x=windows->image.x+event.xmotion.x;
11721 roi_info.y=windows->image.y+event.xmotion.y;
11722 break;
11723 }
11724 case SelectionRequest:
11725 {
11726 XSelectionEvent
11727 notify;
11728
11729 XSelectionRequestEvent
11730 *request;
11731
11732
11733
11734
11735 (void) FormatMagickString(text,MaxTextExtent,"%lux%lu%+ld%+ld",
11736 roi_info.width,roi_info.height,roi_info.x,roi_info.y);
11737 request=(&(event.xselectionrequest));
11738 (void) XChangeProperty(request->display,request->requestor,
11739 request->property,request->target,8,PropModeReplace,
11740 (unsigned char *) text,(int) strlen(text));
11741 notify.type=SelectionNotify;
11742 notify.display=request->display;
11743 notify.requestor=request->requestor;
11744 notify.selection=request->selection;
11745 notify.target=request->target;
11746 notify.time=request->time;
11747 if (request->property == None)
11748 notify.property=request->target;
11749 else
11750 notify.property=request->property;
11751 (void) XSendEvent(request->display,request->requestor,False,0,
11752 (XEvent *) ¬ify);
11753 }
11754 default:
11755 break;
11756 }
11757 if ((state & UpdateConfigurationState) != 0)
11758 {
11759 (void) XPutBackEvent(display,&event);
11760 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11761 break;
11762 }
11763 } while ((state & ExitState) == 0);
11764 } while ((state & ExitState) == 0);
11765 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11766 XSetCursorState(display,windows,MagickFalse);
11767 if ((state & EscapeState) != 0)
11768 return(MagickTrue);
11769 return(MagickTrue);
11770 }
11771
11772
11773
11774
11775
11776
11777
11778
11779
11780
11781
11782
11783
11784
11785
11786
11787
11788
11789
11790
11791
11792
11793
11794
11795
11796
11797
11798
11799
11800
11801
11802
11803
11804
11805
11806
11807 static MagickBooleanType XRotateImage(Display *display,
11808 XResourceInfo *resource_info,XWindows *windows,double degrees,Image **image)
11809 {
11810 static const char
11811 *RotateMenu[] =
11812 {
11813 "Pixel Color",
11814 "Direction",
11815 "Help",
11816 "Dismiss",
11817 (char *) NULL
11818 };
11819
11820 static ModeType
11821 direction = HorizontalRotateCommand;
11822
11823 static const ModeType
11824 DirectionCommands[] =
11825 {
11826 HorizontalRotateCommand,
11827 VerticalRotateCommand
11828 },
11829 RotateCommands[] =
11830 {
11831 RotateColorCommand,
11832 RotateDirectionCommand,
11833 RotateHelpCommand,
11834 RotateDismissCommand
11835 };
11836
11837 static unsigned int
11838 pen_id = 0;
11839
11840 char
11841 command[MaxTextExtent],
11842 text[MaxTextExtent];
11843
11844 Image
11845 *rotate_image;
11846
11847 int
11848 id,
11849 x,
11850 y;
11851
11852 MagickRealType
11853 normalized_degrees;
11854
11855 register int
11856 i;
11857
11858 unsigned int
11859 height,
11860 rotations,
11861 width;
11862
11863 if (degrees == 0.0)
11864 {
11865 unsigned int
11866 distance;
11867
11868 unsigned long
11869 state;
11870
11871 XEvent
11872 event;
11873
11874 XSegment
11875 rotate_info;
11876
11877
11878
11879
11880 (void) CloneString(&windows->command.name,"Rotate");
11881 windows->command.data=2;
11882 (void) XCommandWidget(display,windows,RotateMenu,(XEvent *) NULL);
11883 (void) XMapRaised(display,windows->command.id);
11884 XClientMessage(display,windows->image.id,windows->im_protocols,
11885 windows->im_update_widget,CurrentTime);
11886
11887
11888
11889 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
11890 XQueryPosition(display,windows->image.id,&x,&y);
11891 rotate_info.x1=x;
11892 rotate_info.y1=y;
11893 rotate_info.x2=x;
11894 rotate_info.y2=y;
11895 state=DefaultState;
11896 do
11897 {
11898 XHighlightLine(display,windows->image.id,
11899 windows->image.highlight_context,&rotate_info);
11900
11901
11902
11903 XScreenEvent(display,windows,&event);
11904 XHighlightLine(display,windows->image.id,
11905 windows->image.highlight_context,&rotate_info);
11906 if (event.xany.window == windows->command.id)
11907 {
11908
11909
11910
11911 id=XCommandWidget(display,windows,RotateMenu,&event);
11912 if (id < 0)
11913 continue;
11914 (void) XSetFunction(display,windows->image.highlight_context,
11915 GXcopy);
11916 switch (RotateCommands[id])
11917 {
11918 case RotateColorCommand:
11919 {
11920 const char
11921 *ColorMenu[MaxNumberPens];
11922
11923 int
11924 pen_number;
11925
11926 XColor
11927 color;
11928
11929
11930
11931
11932 for (i=0; i < (int) (MaxNumberPens-2); i++)
11933 ColorMenu[i]=resource_info->pen_colors[i];
11934 ColorMenu[MaxNumberPens-2]="Browser...";
11935 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
11936
11937
11938
11939 pen_number=XMenuWidget(display,windows,RotateMenu[id],
11940 (const char **) ColorMenu,command);
11941 if (pen_number < 0)
11942 break;
11943 if (pen_number == (MaxNumberPens-2))
11944 {
11945 static char
11946 color_name[MaxTextExtent] = "gray";
11947
11948
11949
11950
11951 resource_info->pen_colors[pen_number]=color_name;
11952 XColorBrowserWidget(display,windows,"Select",color_name);
11953 if (*color_name == '\0')
11954 break;
11955 }
11956
11957
11958
11959 (void) XParseColor(display,windows->map_info->colormap,
11960 resource_info->pen_colors[pen_number],&color);
11961 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
11962 (unsigned int) MaxColors,&color);
11963 windows->pixel_info->pen_colors[pen_number]=color;
11964 pen_id=(unsigned int) pen_number;
11965 break;
11966 }
11967 case RotateDirectionCommand:
11968 {
11969 static const char
11970 *Directions[] =
11971 {
11972 "horizontal",
11973 "vertical",
11974 (char *) NULL,
11975 };
11976
11977
11978
11979
11980 id=XMenuWidget(display,windows,RotateMenu[id],
11981 Directions,command);
11982 if (id >= 0)
11983 direction=DirectionCommands[id];
11984 break;
11985 }
11986 case RotateHelpCommand:
11987 {
11988 XTextViewWidget(display,resource_info,windows,MagickFalse,
11989 "Help Viewer - Image Rotation",ImageRotateHelp);
11990 break;
11991 }
11992 case RotateDismissCommand:
11993 {
11994
11995
11996
11997 state|=EscapeState;
11998 state|=ExitState;
11999 break;
12000 }
12001 default:
12002 break;
12003 }
12004 (void) XSetFunction(display,windows->image.highlight_context,
12005 GXinvert);
12006 continue;
12007 }
12008 switch (event.type)
12009 {
12010 case ButtonPress:
12011 {
12012 if (event.xbutton.button != Button1)
12013 break;
12014 if (event.xbutton.window != windows->image.id)
12015 break;
12016
12017
12018
12019 (void) XSetFunction(display,windows->image.highlight_context,
12020 GXcopy);
12021 rotate_info.x1=event.xbutton.x;
12022 rotate_info.y1=event.xbutton.y;
12023 state|=ExitState;
12024 break;
12025 }
12026 case ButtonRelease:
12027 break;
12028 case Expose:
12029 break;
12030 case KeyPress:
12031 {
12032 char
12033 command[MaxTextExtent];
12034
12035 KeySym
12036 key_symbol;
12037
12038 if (event.xkey.window != windows->image.id)
12039 break;
12040
12041
12042
12043 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
12044 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12045 switch ((int) key_symbol)
12046 {
12047 case XK_Escape:
12048 case XK_F20:
12049 {
12050
12051
12052
12053 state|=EscapeState;
12054 state|=ExitState;
12055 break;
12056 }
12057 case XK_F1:
12058 case XK_Help:
12059 {
12060 (void) XSetFunction(display,windows->image.highlight_context,
12061 GXcopy);
12062 XTextViewWidget(display,resource_info,windows,MagickFalse,
12063 "Help Viewer - Image Rotation",ImageRotateHelp);
12064 (void) XSetFunction(display,windows->image.highlight_context,
12065 GXinvert);
12066 break;
12067 }
12068 default:
12069 {
12070 (void) XBell(display,0);
12071 break;
12072 }
12073 }
12074 break;
12075 }
12076 case MotionNotify:
12077 {
12078 rotate_info.x1=event.xmotion.x;
12079 rotate_info.y1=event.xmotion.y;
12080 }
12081 }
12082 rotate_info.x2=rotate_info.x1;
12083 rotate_info.y2=rotate_info.y1;
12084 if (direction == HorizontalRotateCommand)
12085 rotate_info.x2+=32;
12086 else
12087 rotate_info.y2-=32;
12088 } while ((state & ExitState) == 0);
12089 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12090 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12091 if ((state & EscapeState) != 0)
12092 return(MagickTrue);
12093
12094
12095
12096 distance=0;
12097 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
12098 state=DefaultState;
12099 do
12100 {
12101 if (distance > 9)
12102 {
12103
12104
12105
12106 if (windows->info.mapped == MagickFalse)
12107 (void) XMapWindow(display,windows->info.id);
12108 (void) FormatMagickString(text,MaxTextExtent," %g",
12109 direction == VerticalRotateCommand ? degrees-90.0 : degrees);
12110 XInfoWidget(display,windows,text);
12111 XHighlightLine(display,windows->image.id,
12112 windows->image.highlight_context,&rotate_info);
12113 }
12114 else
12115 if (windows->info.mapped != MagickFalse)
12116 (void) XWithdrawWindow(display,windows->info.id,
12117 windows->info.screen);
12118
12119
12120
12121 XScreenEvent(display,windows,&event);
12122 if (distance > 9)
12123 XHighlightLine(display,windows->image.id,
12124 windows->image.highlight_context,&rotate_info);
12125 switch (event.type)
12126 {
12127 case ButtonPress:
12128 break;
12129 case ButtonRelease:
12130 {
12131
12132
12133
12134 rotate_info.x2=event.xbutton.x;
12135 rotate_info.y2=event.xbutton.y;
12136 state|=ExitState;
12137 break;
12138 }
12139 case Expose:
12140 break;
12141 case MotionNotify:
12142 {
12143 rotate_info.x2=event.xmotion.x;
12144 rotate_info.y2=event.xmotion.y;
12145 }
12146 default:
12147 break;
12148 }
12149
12150
12151
12152 if (rotate_info.x2 < 0)
12153 rotate_info.x2=0;
12154 else
12155 if (rotate_info.x2 > (int) windows->image.width)
12156 rotate_info.x2=(short) windows->image.width;
12157 if (rotate_info.y2 < 0)
12158 rotate_info.y2=0;
12159 else
12160 if (rotate_info.y2 > (int) windows->image.height)
12161 rotate_info.y2=(short) windows->image.height;
12162
12163
12164
12165 degrees=0.0;
12166 distance=(unsigned int)
12167 ((rotate_info.x2-rotate_info.x1+1)*(rotate_info.x2-rotate_info.x1+1))+
12168 ((rotate_info.y2-rotate_info.y1+1)*(rotate_info.y2-rotate_info.y1+1));
12169 if (distance > 9)
12170 degrees=RadiansToDegrees(-atan2((double) (rotate_info.y2-
12171 rotate_info.y1),(double) (rotate_info.x2-rotate_info.x1)));
12172 } while ((state & ExitState) == 0);
12173 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12174 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12175 if (distance <= 9)
12176 return(MagickTrue);
12177 }
12178 if (direction == VerticalRotateCommand)
12179 degrees-=90.0;
12180 if (degrees == 0.0)
12181 return(MagickTrue);
12182
12183
12184
12185 normalized_degrees=degrees;
12186 while (normalized_degrees < -45.0)
12187 normalized_degrees+=360.0;
12188 for (rotations=0; normalized_degrees > 45.0; rotations++)
12189 normalized_degrees-=90.0;
12190 if (normalized_degrees != 0.0)
12191 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image);
12192 XSetCursorState(display,windows,MagickTrue);
12193 XCheckRefreshWindows(display,windows);
12194 (*image)->background_color.red=ScaleShortToQuantum(
12195 windows->pixel_info->pen_colors[pen_id].red);
12196 (*image)->background_color.green=ScaleShortToQuantum(
12197 windows->pixel_info->pen_colors[pen_id].green);
12198 (*image)->background_color.blue=ScaleShortToQuantum(
12199 windows->pixel_info->pen_colors[pen_id].blue);
12200 rotate_image=RotateImage(*image,degrees,&(*image)->exception);
12201 XSetCursorState(display,windows,MagickFalse);
12202 if (rotate_image == (Image *) NULL)
12203 return(MagickFalse);
12204 *image=DestroyImage(*image);
12205 *image=rotate_image;
12206 if (windows->image.crop_geometry != (char *) NULL)
12207 {
12208
12209
12210
12211 width=(unsigned int) (*image)->columns;
12212 height=(unsigned int) (*image)->rows;
12213 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
12214 switch (rotations % 4)
12215 {
12216 default:
12217 case 0:
12218 break;
12219 case 1:
12220 {
12221
12222
12223
12224 (void) FormatMagickString(windows->image.crop_geometry,MaxTextExtent,
12225 "%ux%u%+d%+d",height,width,(int) (*image)->columns-
12226 (int) height-y,x);
12227 break;
12228 }
12229 case 2:
12230 {
12231
12232
12233
12234 (void) FormatMagickString(windows->image.crop_geometry,MaxTextExtent,
12235 "%ux%u%+d%+d",width,height,(int) width-x,(int) height-y);
12236 break;
12237 }
12238 case 3:
12239 {
12240
12241
12242
12243 (void) FormatMagickString(windows->image.crop_geometry,MaxTextExtent,
12244 "%ux%u%+d%+d",height,width,y,(int) (*image)->rows-(int) width-x);
12245 break;
12246 }
12247 }
12248 }
12249 if (windows->image.orphan != MagickFalse)
12250 return(MagickTrue);
12251 if (normalized_degrees != 0.0)
12252 {
12253
12254
12255
12256 windows->image.window_changes.width=(int) (*image)->columns;
12257 windows->image.window_changes.height=(int) (*image)->rows;
12258 if (windows->image.crop_geometry != (char *) NULL)
12259 {
12260
12261
12262
12263 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
12264 &width,&height);
12265 windows->image.window_changes.width=(int) width;
12266 windows->image.window_changes.height=(int) height;
12267 }
12268 XConfigureImageColormap(display,resource_info,windows,*image);
12269 }
12270 else
12271 if (((rotations % 4) == 1) || ((rotations % 4) == 3))
12272 {
12273 windows->image.window_changes.width=windows->image.ximage->height;
12274 windows->image.window_changes.height=windows->image.ximage->width;
12275 }
12276
12277
12278
12279 (void) XConfigureImage(display,resource_info,windows,*image);
12280 return(MagickTrue);
12281 }
12282
12283
12284
12285
12286
12287
12288
12289
12290
12291
12292
12293
12294
12295
12296
12297
12298
12299
12300
12301
12302
12303
12304
12305
12306
12307
12308
12309
12310
12311
12312
12313
12314 static MagickBooleanType XSaveImage(Display *display,
12315 XResourceInfo *resource_info,XWindows *windows,Image *image)
12316 {
12317 char
12318 filename[MaxTextExtent],
12319 geometry[MaxTextExtent];
12320
12321 Image
12322 *save_image;
12323
12324 ImageInfo
12325 *image_info;
12326
12327 MagickStatusType
12328 status;
12329
12330
12331
12332
12333 if (resource_info->write_filename != (char *) NULL)
12334 (void) CopyMagickString(filename,resource_info->write_filename,
12335 MaxTextExtent);
12336 else
12337 {
12338 char
12339 path[MaxTextExtent];
12340
12341 int
12342 status;
12343
12344 GetPathComponent(image->filename,HeadPath,path);
12345 GetPathComponent(image->filename,TailPath,filename);
12346 status=chdir(path);
12347 if (status == -1)
12348 (void) ThrowMagickException(&image->exception,GetMagickModule(),
12349 FileOpenError,"UnableToOpenFile","%s",path);
12350 }
12351 XFileBrowserWidget(display,windows,"Save",filename);
12352 if (*filename == '\0')
12353 return(MagickTrue);
12354 if (IsPathAccessible(filename) != MagickFalse)
12355 {
12356 int
12357 status;
12358
12359
12360
12361
12362 status=XConfirmWidget(display,windows,"Overwrite",filename);
12363 if (status <= 0)
12364 return(MagickTrue);
12365 }
12366 image_info=CloneImageInfo(resource_info->image_info);
12367 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
12368 (void) SetImageInfo(image_info,MagickFalse,&image->exception);
12369 if ((LocaleCompare(image_info->magick,"JPEG") == 0) ||
12370 (LocaleCompare(image_info->magick,"JPG") == 0))
12371 {
12372 char
12373 quality[MaxTextExtent];
12374
12375 int
12376 status;
12377
12378
12379
12380
12381 (void) FormatMagickString(quality,MaxTextExtent,"%lu",image->quality);
12382 status=XDialogWidget(display,windows,"Save","Enter JPEG quality:",
12383 quality);
12384 if (*quality == '\0')
12385 return(MagickTrue);
12386 image->quality=(unsigned long) atol(quality);
12387 image_info->interlace=status != 0 ? NoInterlace : PlaneInterlace;
12388 }
12389 if ((LocaleCompare(image_info->magick,"EPS") == 0) ||
12390 (LocaleCompare(image_info->magick,"PDF") == 0) ||
12391 (LocaleCompare(image_info->magick,"PS") == 0) ||
12392 (LocaleCompare(image_info->magick,"PS2") == 0))
12393 {
12394 char
12395 geometry[MaxTextExtent];
12396
12397
12398
12399
12400 (void) FormatMagickString(geometry,MaxTextExtent,PSPageGeometry);
12401 if (LocaleCompare(image_info->magick,"PDF") == 0)
12402 (void) FormatMagickString(geometry,MaxTextExtent,PSPageGeometry);
12403 if (image_info->page != (char *) NULL)
12404 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
12405 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
12406 "Select page geometry:",geometry);
12407 if (*geometry != '\0')
12408 image_info->page=GetPageGeometry(geometry);
12409 }
12410
12411
12412
12413 XSetCursorState(display,windows,MagickTrue);
12414 XCheckRefreshWindows(display,windows);
12415 save_image=CloneImage(image,0,0,MagickTrue,&image->exception);
12416 if (save_image == (Image *) NULL)
12417 return(MagickFalse);
12418 (void) FormatMagickString(geometry,MaxTextExtent,"%dx%d!",
12419 windows->image.ximage->width,windows->image.ximage->height);
12420 (void) TransformImage(&save_image,windows->image.crop_geometry,geometry);
12421
12422
12423
12424 (void) CopyMagickString(save_image->filename,filename,MaxTextExtent);
12425 status=WriteImage(image_info,save_image);
12426 if (status != MagickFalse)
12427 image->taint=MagickFalse;
12428 save_image=DestroyImage(save_image);
12429 image_info=DestroyImageInfo(image_info);
12430 XSetCursorState(display,windows,MagickFalse);
12431 return(status != 0 ? MagickTrue : MagickFalse);
12432 }
12433
12434
12435
12436
12437
12438
12439
12440
12441
12442
12443
12444
12445
12446
12447
12448
12449
12450
12451
12452
12453
12454
12455
12456
12457
12458
12459
12460
12461
12462
12463
12464 #if defined(__cplusplus) || defined(c_plusplus)
12465 extern "C" {
12466 #endif
12467
12468 static int XPredicate(Display *magick_unused(display),XEvent *event,char *data)
12469 {
12470 register XWindows
12471 *windows;
12472
12473 windows=(XWindows *) data;
12474 if ((event->type == ClientMessage) &&
12475 (event->xclient.window == windows->image.id))
12476 return(MagickFalse);
12477 return(MagickTrue);
12478 }
12479
12480 #if defined(__cplusplus) || defined(c_plusplus)
12481 }
12482 #endif
12483
12484 static void XScreenEvent(Display *display,XWindows *windows,XEvent *event)
12485 {
12486 register int
12487 x,
12488 y;
12489
12490 (void) XIfEvent(display,event,XPredicate,(char *) windows);
12491 if (event->xany.window == windows->command.id)
12492 return;
12493 switch (event->type)
12494 {
12495 case ButtonPress:
12496 case ButtonRelease:
12497 {
12498 if ((event->xbutton.button == Button3) &&
12499 (event->xbutton.state & Mod1Mask))
12500 {
12501
12502
12503
12504 event->xbutton.button=Button2;
12505 event->xbutton.state&=(~Mod1Mask);
12506 }
12507 if (event->xbutton.window == windows->backdrop.id)
12508 {
12509 (void) XSetInputFocus(display,event->xbutton.window,RevertToParent,
12510 event->xbutton.time);
12511 break;
12512 }
12513 if (event->xbutton.window == windows->pan.id)
12514 {
12515 XPanImage(display,windows,event);
12516 break;
12517 }
12518 if (event->xbutton.window == windows->image.id)
12519 if (event->xbutton.button == Button2)
12520 {
12521
12522
12523
12524 x=event->xbutton.x;
12525 y=event->xbutton.y;
12526 if (x < 0)
12527 x=0;
12528 else
12529 if (x >= (int) windows->image.width)
12530 x=(int) (windows->image.width-1);
12531 windows->magnify.x=windows->image.x+x;
12532 if (y < 0)
12533 y=0;
12534 else
12535 if (y >= (int) windows->image.height)
12536 y=(int) (windows->image.height-1);
12537 windows->magnify.y=windows->image.y+y;
12538 if (windows->magnify.mapped == MagickFalse)
12539 (void) XMapRaised(display,windows->magnify.id);
12540 XMakeMagnifyImage(display,windows);
12541 if (event->type == ButtonRelease)
12542 (void) XWithdrawWindow(display,windows->info.id,
12543 windows->info.screen);
12544 break;
12545 }
12546 break;
12547 }
12548 case ClientMessage:
12549 {
12550
12551
12552
12553 if (event->xclient.message_type != windows->wm_protocols)
12554 break;
12555 if (*event->xclient.data.l != (long) windows->wm_delete_window)
12556 break;
12557 if (event->xclient.window == windows->magnify.id)
12558 {
12559 (void) XWithdrawWindow(display,windows->magnify.id,
12560 windows->magnify.screen);
12561 break;
12562 }
12563 break;
12564 }
12565 case ConfigureNotify:
12566 {
12567 if (event->xconfigure.window == windows->magnify.id)
12568 {
12569 unsigned int
12570 magnify;
12571
12572
12573
12574
12575 windows->magnify.width=(unsigned int) event->xconfigure.width;
12576 windows->magnify.height=(unsigned int) event->xconfigure.height;
12577 if (windows->magnify.mapped == MagickFalse)
12578 break;
12579 magnify=1;
12580 while ((int) magnify <= event->xconfigure.width)
12581 magnify<<=1;
12582 while ((int) magnify <= event->xconfigure.height)
12583 magnify<<=1;
12584 magnify>>=1;
12585 if (((int) magnify != event->xconfigure.width) ||
12586 ((int) magnify != event->xconfigure.height))
12587 {
12588 XWindowChanges
12589 window_changes;
12590
12591 window_changes.width=(int) magnify;
12592 window_changes.height=(int) magnify;
12593 (void) XReconfigureWMWindow(display,windows->magnify.id,
12594 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
12595 &window_changes);
12596 break;
12597 }
12598 XMakeMagnifyImage(display,windows);
12599 break;
12600 }
12601 break;
12602 }
12603 case Expose:
12604 {
12605 if (event->xexpose.window == windows->image.id)
12606 {
12607 XRefreshWindow(display,&windows->image,event);
12608 break;
12609 }
12610 if (event->xexpose.window == windows->pan.id)
12611 if (event->xexpose.count == 0)
12612 {
12613 XDrawPanRectangle(display,windows);
12614 break;
12615 }
12616 if (event->xexpose.window == windows->magnify.id)
12617 if (event->xexpose.count == 0)
12618 {
12619 XMakeMagnifyImage(display,windows);
12620 break;
12621 }
12622 break;
12623 }
12624 case KeyPress:
12625 {
12626 char
12627 command[MaxTextExtent];
12628
12629 KeySym
12630 key_symbol;
12631
12632 if (event->xkey.window != windows->magnify.id)
12633 break;
12634
12635
12636
12637 (void) XLookupString((XKeyEvent *) &event->xkey,command,(int)
12638 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12639 XMagnifyWindowCommand(display,windows,event->xkey.state,key_symbol);
12640 break;
12641 }
12642 case MapNotify:
12643 {
12644 if (event->xmap.window == windows->magnify.id)
12645 {
12646 windows->magnify.mapped=MagickTrue;
12647 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12648 break;
12649 }
12650 if (event->xmap.window == windows->info.id)
12651 {
12652 windows->info.mapped=MagickTrue;
12653 break;
12654 }
12655 break;
12656 }
12657 case MotionNotify:
12658 {
12659 while (XCheckMaskEvent(display,ButtonMotionMask,event)) ;
12660 if (event->xmotion.window == windows->image.id)
12661 if (windows->magnify.mapped != MagickFalse)
12662 {
12663
12664
12665
12666 x=event->xmotion.x;
12667 y=event->xmotion.y;
12668 if (x < 0)
12669 x=0;
12670 else
12671 if (x >= (int) windows->image.width)
12672 x=(int) (windows->image.width-1);
12673 windows->magnify.x=windows->image.x+x;
12674 if (y < 0)
12675 y=0;
12676 else
12677 if (y >= (int) windows->image.height)
12678 y=(int) (windows->image.height-1);
12679 windows->magnify.y=windows->image.y+y;
12680 XMakeMagnifyImage(display,windows);
12681 }
12682 break;
12683 }
12684 case UnmapNotify:
12685 {
12686 if (event->xunmap.window == windows->magnify.id)
12687 {
12688 windows->magnify.mapped=MagickFalse;
12689 break;
12690 }
12691 if (event->xunmap.window == windows->info.id)
12692 {
12693 windows->info.mapped=MagickFalse;
12694 break;
12695 }
12696 break;
12697 }
12698 default:
12699 break;
12700 }
12701 }
12702
12703
12704
12705
12706
12707
12708
12709
12710
12711
12712
12713
12714
12715
12716
12717
12718
12719
12720
12721
12722
12723
12724
12725
12726
12727
12728
12729
12730
12731
12732
12733
12734
12735 static void XSetCropGeometry(Display *display,XWindows *windows,
12736 RectangleInfo *crop_info,Image *image)
12737 {
12738 char
12739 text[MaxTextExtent];
12740
12741 int
12742 x,
12743 y;
12744
12745 MagickRealType
12746 scale_factor;
12747
12748 unsigned int
12749 height,
12750 width;
12751
12752 if (windows->info.mapped != MagickFalse)
12753 {
12754
12755
12756
12757 (void) FormatMagickString(text,MaxTextExtent," %lux%lu%+ld%+ld",
12758 crop_info->width,crop_info->height,crop_info->x,crop_info->y);
12759 XInfoWidget(display,windows,text);
12760 }
12761
12762
12763
12764 x=0;
12765 y=0;
12766 width=(unsigned int) image->columns;
12767 height=(unsigned int) image->rows;
12768 if (windows->image.crop_geometry != (char *) NULL)
12769 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
12770 else
12771 windows->image.crop_geometry=AcquireString((char *) NULL);
12772
12773
12774
12775 scale_factor=(MagickRealType) width/windows->image.ximage->width;
12776 if (crop_info->x > 0)
12777 x+=(int) (scale_factor*crop_info->x+0.5);
12778 width=(unsigned int) (scale_factor*crop_info->width+0.5);
12779 if (width == 0)
12780 width=1;
12781 scale_factor=(MagickRealType) height/windows->image.ximage->height;
12782 if (crop_info->y > 0)
12783 y+=(int) (scale_factor*crop_info->y+0.5);
12784 height=(unsigned int) (scale_factor*crop_info->height+0.5);
12785 if (height == 0)
12786 height=1;
12787 (void) FormatMagickString(windows->image.crop_geometry,MaxTextExtent,
12788 "%ux%u%+d%+d",width,height,x,y);
12789 }
12790
12791
12792
12793
12794
12795
12796
12797
12798
12799
12800
12801
12802
12803
12804
12805
12806
12807
12808
12809
12810
12811
12812
12813
12814
12815
12816
12817
12818
12819
12820
12821
12822
12823
12824
12825
12826
12827
12828
12829 static Image *XTileImage(Display *display,XResourceInfo *resource_info,
12830 XWindows *windows,Image *image,XEvent *event)
12831 {
12832 static const char
12833 *VerbMenu[] =
12834 {
12835 "Load",
12836 "Next",
12837 "Former",
12838 "Delete",
12839 "Update",
12840 (char *) NULL,
12841 };
12842
12843 static const ModeType
12844 TileCommands[] =
12845 {
12846 TileLoadCommand,
12847 TileNextCommand,
12848 TileFormerCommand,
12849 TileDeleteCommand,
12850 TileUpdateCommand
12851 };
12852
12853 char
12854 command[MaxTextExtent],
12855 filename[MaxTextExtent];
12856
12857 Image
12858 *tile_image;
12859
12860 int
12861 id,
12862 status,
12863 tile,
12864 x,
12865 y;
12866
12867 MagickRealType
12868 scale_factor;
12869
12870 register char
12871 *p,
12872 *q;
12873
12874 register int
12875 i;
12876
12877 unsigned int
12878 height,
12879 width;
12880
12881
12882
12883
12884 x=0;
12885 y=0;
12886 width=(unsigned int) image->columns;
12887 height=(unsigned int) image->rows;
12888 if (windows->image.crop_geometry != (char *) NULL)
12889 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
12890 scale_factor=(MagickRealType) width/windows->image.ximage->width;
12891 event->xbutton.x+=windows->image.x;
12892 event->xbutton.x=(int) (scale_factor*event->xbutton.x+x+0.5);
12893 scale_factor=(MagickRealType) height/windows->image.ximage->height;
12894 event->xbutton.y+=windows->image.y;
12895 event->xbutton.y=(int) (scale_factor*event->xbutton.y+y+0.5);
12896
12897
12898
12899 width=(unsigned int) image->columns;
12900 height=(unsigned int) image->rows;
12901 x=0;
12902 y=0;
12903 (void) XParseGeometry(image->montage,&x,&y,&width,&height);
12904 tile=((event->xbutton.y-y)/height)*(((int) image->columns-x)/width)+
12905 (event->xbutton.x-x)/width;
12906 if (tile < 0)
12907 {
12908
12909
12910
12911 (void) XBell(display,0);
12912 return((Image *) NULL);
12913 }
12914
12915
12916
12917 p=image->directory;
12918 for (i=tile; (i != 0) && (*p != '\0'); )
12919 {
12920 if (*p == '\n')
12921 i--;
12922 p++;
12923 }
12924 if (*p == '\0')
12925 {
12926
12927
12928
12929 (void) XBell(display,0);
12930 return((Image *) NULL);
12931 }
12932
12933
12934
12935 id=XMenuWidget(display,windows,"Tile Verb",VerbMenu,command);
12936 if (id < 0)
12937 return((Image *) NULL);
12938 q=p;
12939 while ((*q != '\n') && (*q != '\0'))
12940 q++;
12941 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
12942
12943
12944
12945 XSetCursorState(display,windows,MagickTrue);
12946 XCheckRefreshWindows(display,windows);
12947 tile_image=NewImageList();
12948 switch (TileCommands[id])
12949 {
12950 case TileLoadCommand:
12951 {
12952
12953
12954
12955 XCheckRefreshWindows(display,windows);
12956 (void) CopyMagickString(resource_info->image_info->magick,"MIFF",
12957 MaxTextExtent);
12958 (void) CopyMagickString(resource_info->image_info->filename,filename,
12959 MaxTextExtent);
12960 tile_image=ReadImage(resource_info->image_info,&image->exception);
12961 CatchException(&image->exception);
12962 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12963 break;
12964 }
12965 case TileNextCommand:
12966 {
12967
12968
12969
12970 XClientMessage(display,windows->image.id,windows->im_protocols,
12971 windows->im_next_image,CurrentTime);
12972 break;
12973 }
12974 case TileFormerCommand:
12975 {
12976
12977
12978
12979 XClientMessage(display,windows->image.id,windows->im_protocols,
12980 windows->im_former_image,CurrentTime);
12981 break;
12982 }
12983 case TileDeleteCommand:
12984 {
12985
12986
12987
12988 if (IsPathAccessible(filename) == MagickFalse)
12989 {
12990 XNoticeWidget(display,windows,"Image file does not exist:",filename);
12991 break;
12992 }
12993 status=XConfirmWidget(display,windows,"Really delete tile",filename);
12994 if (status <= 0)
12995 break;
12996 status=remove(filename) != 0 ? MagickTrue : MagickFalse;
12997 if (status != MagickFalse)
12998 {
12999 XNoticeWidget(display,windows,"Unable to delete image file:",
13000 filename);
13001 break;
13002 }
13003 }
13004 case TileUpdateCommand:
13005 {
13006 ExceptionInfo
13007 *exception;
13008
13009 int
13010 x_offset,
13011 y_offset;
13012
13013 PixelPacket
13014 pixel;
13015
13016 register int
13017 j;
13018
13019 register PixelPacket
13020 *s;
13021
13022
13023
13024
13025 tile=0;
13026 for (p=image->directory; *p != '\0'; p++)
13027 {
13028 q=p;
13029 while ((*q != '\n') && (*q != '\0'))
13030 q++;
13031 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
13032 p=q;
13033 if (IsPathAccessible(filename) != MagickFalse)
13034 {
13035 tile++;
13036 continue;
13037 }
13038
13039
13040
13041 x_offset=(int) (width*(tile % (((int) image->columns-x)/width))+x);
13042 y_offset=(int) (height*(tile/(((int) image->columns-x)/width))+y);
13043 exception=(&image->exception);
13044 (void) GetOneVirtualPixel(image,0,0,&pixel,exception);
13045 for (i=0; i < (int) height; i++)
13046 {
13047 s=GetAuthenticPixels(image,x_offset,y_offset+i,width,1,exception);
13048 if (s == (PixelPacket *) NULL)
13049 break;
13050 for (j=0; j < (int) width; j++)
13051 *s++=pixel;
13052 if (SyncAuthenticPixels(image,exception) == MagickFalse)
13053 break;
13054 }
13055 tile++;
13056 }
13057 windows->image.window_changes.width=(int) image->columns;
13058 windows->image.window_changes.height=(int) image->rows;
13059 XConfigureImageColormap(display,resource_info,windows,image);
13060 (void) XConfigureImage(display,resource_info,windows,image);
13061 break;
13062 }
13063 default:
13064 break;
13065 }
13066 XSetCursorState(display,windows,MagickFalse);
13067 return(tile_image);
13068 }
13069
13070
13071
13072
13073
13074
13075
13076
13077
13078
13079
13080
13081
13082
13083
13084
13085
13086
13087
13088
13089
13090
13091
13092
13093
13094
13095
13096
13097
13098
13099
13100
13101
13102
13103
13104 static void XTranslateImage(Display *display,XWindows *windows,
13105 Image *image,const KeySym key_symbol)
13106 {
13107 char
13108 text[MaxTextExtent];
13109
13110 int
13111 x,
13112 y;
13113
13114 unsigned int
13115 x_offset,
13116 y_offset;
13117
13118
13119
13120
13121 x_offset=windows->image.width;
13122 y_offset=windows->image.height;
13123 if (image->montage != (char *) NULL)
13124 (void) XParseGeometry(image->montage,&x,&y,&x_offset,&y_offset);
13125 switch ((int) key_symbol)
13126 {
13127 case XK_Home:
13128 case XK_KP_Home:
13129 {
13130 windows->image.x=(int) windows->image.width/2;
13131 windows->image.y=(int) windows->image.height/2;
13132 break;
13133 }
13134 case XK_Left:
13135 case XK_KP_Left:
13136 {
13137 windows->image.x-=x_offset;
13138 break;
13139 }
13140 case XK_Next:
13141 case XK_Up:
13142 case XK_KP_Up:
13143 {
13144 windows->image.y-=y_offset;
13145 break;
13146 }
13147 case XK_Right:
13148 case XK_KP_Right:
13149 {
13150 windows->image.x+=x_offset;
13151 break;
13152 }
13153 case XK_Prior:
13154 case XK_Down:
13155 case XK_KP_Down:
13156 {
13157 windows->image.y+=y_offset;
13158 break;
13159 }
13160 default:
13161 return;
13162 }
13163
13164
13165
13166 if (windows->image.x < 0)
13167 windows->image.x=0;
13168 else
13169 if ((int) (windows->image.x+windows->image.width) >
13170 windows->image.ximage->width)
13171 windows->image.x=windows->image.ximage->width-windows->image.width;
13172 if (windows->image.y < 0)
13173 windows->image.y=0;
13174 else
13175 if ((int) (windows->image.y+windows->image.height) >
13176 windows->image.ximage->height)
13177 windows->image.y=windows->image.ximage->height-windows->image.height;
13178
13179
13180
13181 (void) FormatMagickString(text,MaxTextExtent," %ux%u%+d%+d ",
13182 windows->image.width,windows->image.height,windows->image.x,
13183 windows->image.y);
13184 XInfoWidget(display,windows,text);
13185 XCheckRefreshWindows(display,windows);
13186 XDrawPanRectangle(display,windows);
13187 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
13188 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
13189 }
13190
13191
13192
13193
13194
13195
13196
13197
13198
13199
13200
13201
13202
13203
13204
13205
13206
13207
13208
13209
13210
13211
13212
13213
13214
13215
13216
13217
13218
13219
13220
13221 static MagickBooleanType XTrimImage(Display *display,
13222 XResourceInfo *resource_info,XWindows *windows,Image *image)
13223 {
13224 RectangleInfo
13225 trim_info;
13226
13227 register int
13228 x,
13229 y;
13230
13231 unsigned long
13232 background,
13233 pixel;
13234
13235
13236
13237
13238 XSetCursorState(display,windows,MagickTrue);
13239 XCheckRefreshWindows(display,windows);
13240
13241
13242
13243 background=XGetPixel(windows->image.ximage,0,0);
13244 trim_info.width=(unsigned long) windows->image.ximage->width;
13245 for (x=0; x < windows->image.ximage->width; x++)
13246 {
13247 for (y=0; y < windows->image.ximage->height; y++)
13248 {
13249 pixel=XGetPixel(windows->image.ximage,x,y);
13250 if (pixel != background)
13251 break;
13252 }
13253 if (y < windows->image.ximage->height)
13254 break;
13255 }
13256 trim_info.x=x;
13257 if (trim_info.x == (int) windows->image.ximage->width)
13258 {
13259 XSetCursorState(display,windows,MagickFalse);
13260 return(MagickFalse);
13261 }
13262
13263
13264
13265 background=XGetPixel(windows->image.ximage,windows->image.ximage->width-1,0);
13266 for (x=windows->image.ximage->width-1; x != 0; x--)
13267 {
13268 for (y=0; y < windows->image.ximage->height; y++)
13269 {
13270 pixel=XGetPixel(windows->image.ximage,x,y);
13271 if (pixel != background)
13272 break;
13273 }
13274 if (y < windows->image.ximage->height)
13275 break;
13276 }
13277 trim_info.width=(unsigned long) (x-trim_info.x+1);
13278
13279
13280
13281 background=XGetPixel(windows->image.ximage,0,0);
13282 trim_info.height=(unsigned long) windows->image.ximage->height;
13283 for (y=0; y < windows->image.ximage->height; y++)
13284 {
13285 for (x=0; x < windows->image.ximage->width; x++)
13286 {
13287 pixel=XGetPixel(windows->image.ximage,x,y);
13288 if (pixel != background)
13289 break;
13290 }
13291 if (x < windows->image.ximage->width)
13292 break;
13293 }
13294 trim_info.y=y;
13295
13296
13297
13298 background=XGetPixel(windows->image.ximage,0,windows->image.ximage->height-1);
13299 for (y=windows->image.ximage->height-1; y != 0; y--)
13300 {
13301 for (x=0; x < windows->image.ximage->width; x++)
13302 {
13303 pixel=XGetPixel(windows->image.ximage,x,y);
13304 if (pixel != background)
13305 break;
13306 }
13307 if (x < windows->image.ximage->width)
13308 break;
13309 }
13310 trim_info.height=(unsigned long) y-trim_info.y+1;
13311 if (((unsigned int) trim_info.width != windows->image.width) ||
13312 ((unsigned int) trim_info.height != windows->image.height))
13313 {
13314
13315
13316
13317 XSetCropGeometry(display,windows,&trim_info,image);
13318 windows->image.window_changes.width=(int) trim_info.width;
13319 windows->image.window_changes.height=(int) trim_info.height;
13320 (void) XConfigureImage(display,resource_info,windows,image);
13321 }
13322 XSetCursorState(display,windows,MagickFalse);
13323 return(MagickTrue);
13324 }
13325
13326
13327
13328
13329
13330
13331
13332
13333
13334
13335
13336
13337
13338
13339
13340
13341
13342
13343
13344
13345
13346
13347
13348
13349
13350
13351
13352
13353
13354
13355
13356
13357
13358 static Image *XVisualDirectoryImage(Display *display,
13359 XResourceInfo *resource_info,XWindows *windows)
13360 {
13361 #define TileImageTag "Scale/Image"
13362 #define XClientName "montage"
13363
13364 char
13365 **filelist;
13366
13367 ExceptionInfo
13368 *exception;
13369
13370 Image
13371 *images,
13372 *montage_image,
13373 *next_image,
13374 *thumbnail_image;
13375
13376 ImageInfo
13377 *read_info;
13378
13379 int
13380 number_files;
13381
13382 MagickBooleanType
13383 backdrop;
13384
13385 MagickStatusType
13386 status;
13387
13388 MontageInfo
13389 *montage_info;
13390
13391 RectangleInfo
13392 geometry;
13393
13394 register int
13395 i;
13396
13397 static char
13398 filename[MaxTextExtent] = "\0",
13399 filenames[MaxTextExtent] = "*";
13400
13401 XResourceInfo
13402 background_resources;
13403
13404
13405
13406
13407 XFileBrowserWidget(display,windows,"Directory",filenames);
13408 if (*filenames == '\0')
13409 return((Image *) NULL);
13410
13411
13412
13413 filelist=(char **) AcquireMagickMemory(sizeof(*filelist));
13414 if (filelist == (char **) NULL)
13415 {
13416 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
13417 filenames);
13418 return((Image *) NULL);
13419 }
13420 number_files=1;
13421 filelist[0]=filenames;
13422 status=ExpandFilenames(&number_files,&filelist);
13423 if ((status == MagickFalse) || (number_files == 0))
13424 {
13425 if (number_files == 0)
13426 ThrowXWindowFatalException(ImageError,"NoImagesWereFound",filenames)
13427 else
13428 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
13429 filenames);
13430 return((Image *) NULL);
13431 }
13432
13433
13434
13435 background_resources=(*resource_info);
13436 background_resources.window_id=AcquireString("");
13437 (void) FormatMagickString(background_resources.window_id,MaxTextExtent,
13438 "0x%lx",windows->image.id);
13439 background_resources.backdrop=MagickTrue;
13440
13441
13442
13443 backdrop=(windows->visual_info->klass == TrueColor) ||
13444 (windows->visual_info->klass == DirectColor) ? MagickTrue : MagickFalse;
13445 read_info=CloneImageInfo(resource_info->image_info);
13446 (void) SetImageInfoProgressMonitor(read_info,(MagickProgressMonitor) NULL,
13447 (void *) NULL);
13448 images=NewImageList();
13449 exception=AcquireExceptionInfo();
13450 XSetCursorState(display,windows,MagickTrue);
13451 XCheckRefreshWindows(display,windows);
13452 for (i=0; i < (long) number_files; i++)
13453 {
13454 (void) CopyMagickString(read_info->filename,filelist[i],MaxTextExtent);
13455 filelist[i]=DestroyString(filelist[i]);
13456 *read_info->magick='\0';
13457 (void) CloneString(&read_info->size,DefaultTileGeometry);
13458 next_image=ReadImage(read_info,exception);
13459 CatchException(exception);
13460 if (next_image != (Image *) NULL)
13461 {
13462 (void) DeleteImageProperty(next_image,"label");
13463 (void) SetImageProperty(next_image,"label",DefaultTileLabel);
13464 (void) ParseRegionGeometry(next_image,read_info->size,&geometry,
13465 exception);
13466 thumbnail_image=ThumbnailImage(next_image,geometry.width,
13467 geometry.height,exception);
13468 if (thumbnail_image != (Image *) NULL)
13469 {
13470 next_image=DestroyImage(next_image);
13471 next_image=thumbnail_image;
13472 }
13473 if (backdrop)
13474 {
13475 (void) XDisplayBackgroundImage(display,&background_resources,
13476 next_image);
13477 XSetCursorState(display,windows,MagickTrue);
13478 }
13479 AppendImageToList(&images,next_image);
13480 if (images->progress_monitor != (MagickProgressMonitor) NULL)
13481 {
13482 MagickBooleanType
13483 proceed;
13484
13485 proceed=SetImageProgress(images,LoadImageTag,(MagickOffsetType) i,
13486 (MagickSizeType) number_files);
13487 if (proceed == MagickFalse)
13488 break;
13489 }
13490 }
13491 }
13492 exception=DestroyExceptionInfo(exception);
13493 filelist=(char **) RelinquishMagickMemory(filelist);
13494 read_info=DestroyImageInfo(read_info);
13495 if (images == (Image *) NULL)
13496 {
13497 XSetCursorState(display,windows,MagickFalse);
13498 ThrowXWindowFatalException(ImageError,"NoImagesWereLoaded",filenames);
13499 return((Image *) NULL);
13500 }
13501
13502
13503
13504 montage_info=CloneMontageInfo(resource_info->image_info,(MontageInfo *) NULL);
13505 if (resource_info->font != (char *) NULL)
13506 (void) CloneString(&montage_info->font,resource_info->font);
13507 (void) CopyMagickString(montage_info->filename,filename,MaxTextExtent);
13508 montage_image=MontageImageList(resource_info->image_info,montage_info,
13509 GetFirstImageInList(images),&images->exception);
13510 montage_info=DestroyMontageInfo(montage_info);
13511 images=DestroyImageList(images);
13512 XSetCursorState(display,windows,MagickFalse);
13513 if (montage_image == (Image *) NULL)
13514 return(montage_image);
13515 XClientMessage(display,windows->image.id,windows->im_protocols,
13516 windows->im_next_image,CurrentTime);
13517 return(montage_image);
13518 }
13519
13520
13521
13522
13523
13524
13525
13526
13527
13528
13529
13530
13531
13532
13533
13534
13535
13536
13537
13538
13539
13540
13541
13542
13543
13544
13545
13546
13547
13548 MagickExport MagickBooleanType XDisplayBackgroundImage(Display *display,
13549 XResourceInfo *resource_info,Image *image)
13550 {
13551 char
13552 geometry[MaxTextExtent],
13553 visual_type[MaxTextExtent];
13554
13555 int
13556 height,
13557 status,
13558 width;
13559
13560 RectangleInfo
13561 geometry_info;
13562
13563 static XPixelInfo
13564 pixel;
13565
13566 static XStandardColormap
13567 *map_info;
13568
13569 static XVisualInfo
13570 *visual_info = (XVisualInfo *) NULL;
13571
13572 static XWindowInfo
13573 window_info;
13574
13575 unsigned long
13576 delay;
13577
13578 Window
13579 root_window;
13580
13581 XGCValues
13582 context_values;
13583
13584 XResourceInfo
13585 resources;
13586
13587 XWindowAttributes
13588 window_attributes;
13589
13590
13591
13592
13593 assert(image != (Image *) NULL);
13594 assert(image->signature == MagickSignature);
13595 if (image->debug != MagickFalse)
13596 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
13597 resources=(*resource_info);
13598 window_info.id=(Window) NULL;
13599 root_window=XRootWindow(display,XDefaultScreen(display));
13600 if (LocaleCompare(resources.window_id,"root") == 0)
13601 window_info.id=root_window;
13602 else
13603 {
13604 if (isdigit((unsigned char) *resources.window_id) != 0)
13605 window_info.id=XWindowByID(display,root_window,
13606 (Window) strtol((char *) resources.window_id,(char **) NULL,0));
13607 if (window_info.id == (Window) NULL)
13608 window_info.id=XWindowByName(display,root_window,resources.window_id);
13609 }
13610 if (window_info.id == (Window) NULL)
13611 {
13612 ThrowXWindowFatalException(XServerError,"NoWindowWithSpecifiedIDExists",
13613 resources.window_id);
13614 return(MagickFalse);
13615 }
13616
13617
13618
13619 window_attributes.width=XDisplayWidth(display,XDefaultScreen(display));
13620 window_attributes.height=XDisplayHeight(display,XDefaultScreen(display));
13621 (void) CopyMagickString(visual_type,"default",MaxTextExtent);
13622 status=XGetWindowAttributes(display,window_info.id,&window_attributes);
13623 if (status != 0)
13624 (void) FormatMagickString(visual_type,MaxTextExtent,"0x%lx",
13625 XVisualIDFromVisual(window_attributes.visual));
13626 if (visual_info == (XVisualInfo *) NULL)
13627 {
13628
13629
13630
13631 map_info=XAllocStandardColormap();
13632 if (map_info == (XStandardColormap *) NULL)
13633 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
13634 image->filename);
13635 map_info->colormap=(Colormap) NULL;
13636 pixel.pixels=(unsigned long *) NULL;
13637
13638
13639
13640 resources.map_type=(char *) NULL;
13641 resources.visual_type=visual_type;
13642 visual_info=XBestVisualInfo(display,map_info,&resources);
13643 if (visual_info == (XVisualInfo *) NULL)
13644 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
13645 resources.visual_type);
13646
13647
13648
13649 window_info.ximage=(XImage *) NULL;
13650 window_info.matte_image=(XImage *) NULL;
13651 window_info.pixmap=(Pixmap) NULL;
13652 window_info.matte_pixmap=(Pixmap) NULL;
13653 }
13654
13655
13656
13657 if (window_info.id == root_window)
13658 (void) XDestroyWindowColors(display,root_window);
13659
13660
13661
13662 resources.colormap=SharedColormap;
13663 XMakeStandardColormap(display,visual_info,&resources,image,map_info,&pixel);
13664
13665
13666
13667 context_values.background=pixel.background_color.pixel;
13668 context_values.foreground=pixel.foreground_color.pixel;
13669 pixel.annotate_context=XCreateGC(display,window_info.id,
13670 (unsigned long) (GCBackground | GCForeground),&context_values);
13671 if (pixel.annotate_context == (GC) NULL)
13672 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
13673 image->filename);
13674
13675
13676
13677 window_info.name=AcquireString("\0");
13678 window_info.icon_name=AcquireString("\0");
13679 XGetWindowInfo(display,visual_info,map_info,&pixel,(XFontStruct *) NULL,
13680 &resources,&window_info);
13681
13682
13683
13684 window_info.width=(unsigned int) image->columns;
13685 window_info.height=(unsigned int) image->rows;
13686 if ((image->columns != window_info.width) ||
13687 (image->rows != window_info.height))
13688 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13689 image->filename);
13690 (void) FormatMagickString(geometry,MaxTextExtent,"%ux%u+0+0>",
13691 window_attributes.width,window_attributes.height);
13692 geometry_info.width=window_info.width;
13693 geometry_info.height=window_info.height;
13694 geometry_info.x=window_info.x;
13695 geometry_info.y=window_info.y;
13696 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
13697 &geometry_info.width,&geometry_info.height);
13698 window_info.width=(unsigned int) geometry_info.width;
13699 window_info.height=(unsigned int) geometry_info.height;
13700 window_info.x=(int) geometry_info.x;
13701 window_info.y=(int) geometry_info.y;
13702 status=XMakeImage(display,&resources,&window_info,image,window_info.width,
13703 window_info.height);
13704 if (status == MagickFalse)
13705 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13706 image->filename);
13707 window_info.x=0;
13708 window_info.y=0;
13709 if (image->debug != MagickFalse)
13710 {
13711 (void) LogMagickEvent(X11Event,GetMagickModule(),
13712 "Image: %s[%lu] %lux%lu ",image->filename,image->scene,
13713 image->columns,image->rows);
13714 if (image->colors != 0)
13715 (void) LogMagickEvent(X11Event,GetMagickModule(),"%luc ",image->colors);
13716 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",image->magick);
13717 }
13718
13719
13720
13721 width=(int) window_info.width;
13722 height=(int) window_info.height;
13723 if (resources.backdrop != MagickFalse)
13724 {
13725
13726
13727
13728 window_info.x=(window_attributes.width/2)-
13729 (window_info.ximage->width/2);
13730 window_info.y=(window_attributes.height/2)-
13731 (window_info.ximage->height/2);
13732 width=window_attributes.width;
13733 height=window_attributes.height;
13734 }
13735 if ((resources.image_geometry != (char *) NULL) &&
13736 (*resources.image_geometry != '\0'))
13737 {
13738 char
13739 default_geometry[MaxTextExtent];
13740
13741 int
13742 flags,
13743 gravity;
13744
13745 XSizeHints
13746 *size_hints;
13747
13748
13749
13750
13751 size_hints=XAllocSizeHints();
13752 if (size_hints == (XSizeHints *) NULL)
13753 ThrowXWindowFatalException(ResourceLimitFatalError,
13754 "MemoryAllocationFailed",image->filename);
13755 size_hints->flags=0L;
13756 (void) FormatMagickString(default_geometry,MaxTextExtent,"%dx%d",
13757 width,height);
13758 flags=XWMGeometry(display,visual_info->screen,resources.image_geometry,
13759 default_geometry,window_info.border_width,size_hints,&window_info.x,
13760 &window_info.y,&width,&height,&gravity);
13761 if (flags & (XValue | YValue))
13762 {
13763 width=window_attributes.width;
13764 height=window_attributes.height;
13765 }
13766 (void) XFree((void *) size_hints);
13767 }
13768
13769
13770
13771 window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width,
13772 (unsigned int) height,window_info.depth);
13773 if (window_info.pixmap == (Pixmap) NULL)
13774 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
13775 image->filename);
13776
13777
13778
13779 if (((unsigned int) width > window_info.width) ||
13780 ((unsigned int) height > window_info.height))
13781 (void) XFillRectangle(display,window_info.pixmap,
13782 window_info.annotate_context,0,0,(unsigned int) width,
13783 (unsigned int) height);
13784 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
13785 window_info.ximage,0,0,window_info.x,window_info.y,(unsigned int)
13786 window_info.width,(unsigned int) window_info.height);
13787 (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap);
13788 (void) XClearWindow(display,window_info.id);
13789 delay=1000*image->delay/MagickMax(image->ticks_per_second,1L);
13790 XDelay(display,delay == 0UL ? 10UL : delay);
13791 (void) XSync(display,MagickFalse);
13792 return(window_info.id == root_window ? MagickTrue : MagickFalse);
13793 }
13794
13795
13796
13797
13798
13799
13800
13801
13802
13803
13804
13805
13806
13807
13808
13809
13810
13811
13812
13813
13814
13815
13816
13817
13818
13819
13820
13821
13822
13823
13824
13825
13826
13827
13828
13829
13830
13831
13832 MagickExport Image *XDisplayImage(Display *display,XResourceInfo *resource_info,
13833 char **argv,int argc,Image **image,unsigned long *state)
13834 {
13835 #define MagnifySize 256
13836 #define MagickMenus 10
13837 #define MagickTitle "Commands"
13838
13839 static const char
13840 *CommandMenu[] =
13841 {
13842 "File",
13843 "Edit",
13844 "View",
13845 "Transform",
13846 "Enhance",
13847 "Effects",
13848 "F/X",
13849 "Image Edit",
13850 "Miscellany",
13851 "Help",
13852 (char *) NULL
13853 },
13854 *FileMenu[] =
13855 {
13856 "Open...",
13857 "Next",
13858 "Former",
13859 "Select...",
13860 "Save...",
13861 "Print...",
13862 "Delete...",
13863 "New...",
13864 "Visual Directory...",
13865 "Quit",
13866 (char *) NULL
13867 },
13868 *EditMenu[] =
13869 {
13870 "Undo",
13871 "Redo",
13872 "Cut",
13873 "Copy",
13874 "Paste",
13875 (char *) NULL
13876 },
13877 *ViewMenu[] =
13878 {
13879 "Half Size",
13880 "Original Size",
13881 "Double Size",
13882 "Resize...",
13883 "Apply",
13884 "Refresh",
13885 "Restore",
13886 (char *) NULL
13887 },
13888 *TransformMenu[] =
13889 {
13890 "Crop",
13891 "Chop",
13892 "Flop",
13893 "Flip",
13894 "Rotate Right",
13895 "Rotate Left",
13896 "Rotate...",
13897 "Shear...",
13898 "Roll...",
13899 "Trim Edges",
13900 (char *) NULL
13901 },
13902 *EnhanceMenu[] =
13903 {
13904 "Hue...",
13905 "Saturation...",
13906 "Brightness...",
13907 "Gamma...",
13908 "Spiff",
13909 "Dull",
13910 "Contrast Stretch...",
13911 "Sigmoidal Contrast...",
13912 "Normalize",
13913 "Equalize",
13914 "Negate",
13915 "Grayscale",
13916 "Map...",
13917 "Quantize...",
13918 (char *) NULL
13919 },
13920 *EffectsMenu[] =
13921 {
13922 "Despeckle",
13923 "Emboss",
13924 "Reduce Noise",
13925 "Add Noise...",
13926 "Sharpen...",
13927 "Blur...",
13928 "Threshold...",
13929 "Edge Detect...",
13930 "Spread...",
13931 "Shade...",
13932 "Raise...",
13933 "Segment...",
13934 (char *) NULL
13935 },
13936 *FXMenu[] =
13937 {
13938 "Solarize...",
13939 "Sepia Tone...",
13940 "Swirl...",
13941 "Implode...",
13942 "Vignette...",
13943 "Wave...",
13944 "Oil Paint...",
13945 "Charcoal Draw...",
13946 (char *) NULL
13947 },
13948 *ImageEditMenu[] =
13949 {
13950 "Annotate...",
13951 "Draw...",
13952 "Color...",
13953 "Matte...",
13954 "Composite...",
13955 "Add Border...",
13956 "Add Frame...",
13957 "Comment...",
13958 "Launch...",
13959 "Region of Interest...",
13960 (char *) NULL
13961 },
13962 *MiscellanyMenu[] =
13963 {
13964 "Image Info",
13965 "Zoom Image",
13966 "Show Preview...",
13967 "Show Histogram",
13968 "Show Matte",
13969 "Background...",
13970 "Slide Show...",
13971 "Preferences...",
13972 (char *) NULL
13973 },
13974 *HelpMenu[] =
13975 {
13976 "Overview",
13977 "Browse Documentation",
13978 "About Display",
13979 (char *) NULL
13980 },
13981 *ShortCutsMenu[] =
13982 {
13983 "Next",
13984 "Former",
13985 "Open...",
13986 "Save...",
13987 "Print...",
13988 "Undo",
13989 "Restore",
13990 "Image Info",
13991 "Quit",
13992 (char *) NULL
13993 },
13994 *VirtualMenu[] =
13995 {
13996 "Image Info",
13997 "Print",
13998 "Next",
13999 "Quit",
14000 (char *) NULL
14001 };
14002
14003 static const char
14004 **Menus[MagickMenus] =
14005 {
14006 FileMenu,
14007 EditMenu,
14008 ViewMenu,
14009 TransformMenu,
14010 EnhanceMenu,
14011 EffectsMenu,
14012 FXMenu,
14013 ImageEditMenu,
14014 MiscellanyMenu,
14015 HelpMenu
14016 };
14017
14018 static CommandType
14019 CommandMenus[] =
14020 {
14021 NullCommand,
14022 NullCommand,
14023 NullCommand,
14024 NullCommand,
14025 NullCommand,
14026 NullCommand,
14027 NullCommand,
14028 NullCommand,
14029 NullCommand,
14030 NullCommand,
14031 },
14032 FileCommands[] =
14033 {
14034 OpenCommand,
14035 NextCommand,
14036 FormerCommand,
14037 SelectCommand,
14038 SaveCommand,
14039 PrintCommand,
14040 DeleteCommand,
14041 NewCommand,
14042 VisualDirectoryCommand,
14043 QuitCommand
14044 },
14045 EditCommands[] =
14046 {
14047 UndoCommand,
14048 RedoCommand,
14049 CutCommand,
14050 CopyCommand,
14051 PasteCommand
14052 },
14053 ViewCommands[] =
14054 {
14055 HalfSizeCommand,
14056 OriginalSizeCommand,
14057 DoubleSizeCommand,
14058 ResizeCommand,
14059 ApplyCommand,
14060 RefreshCommand,
14061 RestoreCommand
14062 },
14063 TransformCommands[] =
14064 {
14065 CropCommand,
14066 ChopCommand,
14067 FlopCommand,
14068 FlipCommand,
14069 RotateRightCommand,
14070 RotateLeftCommand,
14071 RotateCommand,
14072 ShearCommand,
14073 RollCommand,
14074 TrimCommand
14075 },
14076 EnhanceCommands[] =
14077 {
14078 HueCommand,
14079 SaturationCommand,
14080 BrightnessCommand,
14081 GammaCommand,
14082 SpiffCommand,
14083 DullCommand,
14084 ContrastStretchCommand,
14085 SigmoidalContrastCommand,
14086 NormalizeCommand,
14087 EqualizeCommand,
14088 NegateCommand,
14089 GrayscaleCommand,
14090 MapCommand,
14091 QuantizeCommand
14092 },
14093 EffectsCommands[] =
14094 {
14095 DespeckleCommand,
14096 EmbossCommand,
14097 ReduceNoiseCommand,
14098 AddNoiseCommand,
14099 SharpenCommand,
14100 BlurCommand,
14101 ThresholdCommand,
14102 EdgeDetectCommand,
14103 SpreadCommand,
14104 ShadeCommand,
14105 RaiseCommand,
14106 SegmentCommand
14107 },
14108 FXCommands[] =
14109 {
14110 SolarizeCommand,
14111 SepiaToneCommand,
14112 SwirlCommand,
14113 ImplodeCommand,
14114 VignetteCommand,
14115 WaveCommand,
14116 OilPaintCommand,
14117 CharcoalDrawCommand
14118 },
14119 ImageEditCommands[] =
14120 {
14121 AnnotateCommand,
14122 DrawCommand,
14123 ColorCommand,
14124 MatteCommand,
14125 CompositeCommand,
14126 AddBorderCommand,
14127 AddFrameCommand,
14128 CommentCommand,
14129 LaunchCommand,
14130 RegionofInterestCommand
14131 },
14132 MiscellanyCommands[] =
14133 {
14134 InfoCommand,
14135 ZoomCommand,
14136 ShowPreviewCommand,
14137 ShowHistogramCommand,
14138 ShowMatteCommand,
14139 BackgroundCommand,
14140 SlideShowCommand,
14141 PreferencesCommand
14142 },
14143 HelpCommands[] =
14144 {
14145 HelpCommand,
14146 BrowseDocumentationCommand,
14147 VersionCommand
14148 },
14149 ShortCutsCommands[] =
14150 {
14151 NextCommand,
14152 FormerCommand,
14153 OpenCommand,
14154 SaveCommand,
14155 PrintCommand,
14156 UndoCommand,
14157 RestoreCommand,
14158 InfoCommand,
14159 QuitCommand
14160 },
14161 VirtualCommands[] =
14162 {
14163 InfoCommand,
14164 PrintCommand,
14165 NextCommand,
14166 QuitCommand
14167 };
14168
14169 static CommandType
14170 *Commands[MagickMenus] =
14171 {
14172 FileCommands,
14173 EditCommands,
14174 ViewCommands,
14175 TransformCommands,
14176 EnhanceCommands,
14177 EffectsCommands,
14178 FXCommands,
14179 ImageEditCommands,
14180 MiscellanyCommands,
14181 HelpCommands
14182 };
14183
14184 char
14185 command[MaxTextExtent],
14186 *cwd,
14187 geometry[MaxTextExtent],
14188 resource_name[MaxTextExtent];
14189
14190 CommandType
14191 command_type;
14192
14193 Image
14194 *display_image,
14195 *nexus;
14196
14197 int
14198 entry,
14199 id;
14200
14201 KeySym
14202 key_symbol;
14203
14204 MagickStatusType
14205 context_mask,
14206 status;
14207
14208 RectangleInfo
14209 geometry_info;
14210
14211 register int
14212 i;
14213
14214 static char
14215 working_directory[MaxTextExtent];
14216
14217 static XPoint
14218 vid_info;
14219
14220 static XWindowInfo
14221 *magick_windows[MaxXWindows];
14222
14223 static unsigned int
14224 number_windows;
14225
14226 struct stat
14227 attributes;
14228
14229 time_t
14230 timer,
14231 timestamp,
14232 update_time;
14233
14234 unsigned int
14235 height,
14236 width;
14237
14238 unsigned long
14239 delay;
14240
14241 WarningHandler
14242 warning_handler;
14243
14244 Window
14245 root_window;
14246
14247 XClassHint
14248 *class_hints;
14249
14250 XEvent
14251 event;
14252
14253 XFontStruct
14254 *font_info;
14255
14256 XGCValues
14257 context_values;
14258
14259 XPixelInfo
14260 *icon_pixel,
14261 *pixel;
14262
14263 XResourceInfo
14264 *icon_resources;
14265
14266 XStandardColormap
14267 *icon_map,
14268 *map_info;
14269
14270 XVisualInfo
14271 *icon_visual,
14272 *visual_info;
14273
14274 XWindowChanges
14275 window_changes;
14276
14277 XWindows
14278 *windows;
14279
14280 XWMHints
14281 *manager_hints;
14282
14283 assert(image != (Image **) NULL);
14284 assert((*image)->signature == MagickSignature);
14285 if ((*image)->debug != MagickFalse)
14286 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
14287 display_image=(*image);
14288 warning_handler=(WarningHandler) NULL;
14289 windows=XSetWindows((XWindows *) ~0);
14290 if (windows != (XWindows *) NULL)
14291 {
14292 int
14293 status;
14294
14295 status=chdir(working_directory);
14296 if (status == -1)
14297 (void) ThrowMagickException(&(*image)->exception,GetMagickModule(),
14298 FileOpenError,"UnableToOpenFile","%s",working_directory);
14299 warning_handler=resource_info->display_warnings ?
14300 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
14301 warning_handler=resource_info->display_warnings ?
14302 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
14303 }
14304 else
14305 {
14306
14307
14308
14309 resource_info->colors=display_image->colors;
14310 windows=XSetWindows(XInitializeWindows(display,resource_info));
14311 if (windows == (XWindows *) NULL)
14312 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
14313 (*image)->filename);
14314
14315
14316
14317 number_windows=0;
14318 magick_windows[number_windows++]=(&windows->icon);
14319 magick_windows[number_windows++]=(&windows->backdrop);
14320 magick_windows[number_windows++]=(&windows->image);
14321 magick_windows[number_windows++]=(&windows->info);
14322 magick_windows[number_windows++]=(&windows->command);
14323 magick_windows[number_windows++]=(&windows->widget);
14324 magick_windows[number_windows++]=(&windows->popup);
14325 magick_windows[number_windows++]=(&windows->magnify);
14326 magick_windows[number_windows++]=(&windows->pan);
14327 for (i=0; i < (int) number_windows; i++)
14328 magick_windows[i]->id=(Window) NULL;
14329 vid_info.x=0;
14330 vid_info.y=0;
14331 }
14332
14333
14334
14335 if (windows->font_info != (XFontStruct *) NULL)
14336 (void) XFreeFont(display,windows->font_info);
14337 windows->font_info=XBestFont(display,resource_info,MagickFalse);
14338 if (windows->font_info == (XFontStruct *) NULL)
14339 ThrowXWindowFatalException(XServerFatalError,"UnableToLoadFont",
14340 resource_info->font);
14341
14342
14343
14344 map_info=windows->map_info;
14345 icon_map=windows->icon_map;
14346 visual_info=windows->visual_info;
14347 icon_visual=windows->icon_visual;
14348 pixel=windows->pixel_info;
14349 icon_pixel=windows->icon_pixel;
14350 font_info=windows->font_info;
14351 icon_resources=windows->icon_resources;
14352 class_hints=windows->class_hints;
14353 manager_hints=windows->manager_hints;
14354 root_window=XRootWindow(display,visual_info->screen);
14355 nexus=NewImageList();
14356 if (display_image->debug != MagickFalse)
14357 {
14358 (void) LogMagickEvent(X11Event,GetMagickModule(),
14359 "Image: %s[%lu] %lux%lu ",display_image->filename,
14360 display_image->scene,display_image->columns,display_image->rows);
14361 if (display_image->colors != 0)
14362 (void) LogMagickEvent(X11Event,GetMagickModule(),"%luc ",
14363 display_image->colors);
14364 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
14365 display_image->magick);
14366 }
14367 XMakeStandardColormap(display,visual_info,resource_info,display_image,
14368 map_info,pixel);
14369 display_image->taint=MagickFalse;
14370
14371
14372
14373 windows->context.id=(Window) NULL;
14374 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14375 resource_info,&windows->context);
14376 (void) CloneString(&class_hints->res_name,"superclass");
14377 (void) CloneString(&class_hints->res_class,resource_info->client_name);
14378 manager_hints->flags=InputHint | StateHint;
14379 manager_hints->input=MagickFalse;
14380 manager_hints->initial_state=WithdrawnState;
14381 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14382 &windows->context);
14383 if (display_image->debug != MagickFalse)
14384 (void) LogMagickEvent(X11Event,GetMagickModule(),
14385 "Window id: 0x%lx (context)",windows->context.id);
14386 context_values.background=pixel->background_color.pixel;
14387 context_values.font=font_info->fid;
14388 context_values.foreground=pixel->foreground_color.pixel;
14389 context_values.graphics_exposures=MagickFalse;
14390 context_mask=(MagickStatusType)
14391 (GCBackground | GCFont | GCForeground | GCGraphicsExposures);
14392 if (pixel->annotate_context != (GC) NULL)
14393 (void) XFreeGC(display,pixel->annotate_context);
14394 pixel->annotate_context=XCreateGC(display,windows->context.id,
14395 context_mask,&context_values);
14396 if (pixel->annotate_context == (GC) NULL)
14397 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14398 display_image->filename);
14399 context_values.background=pixel->depth_color.pixel;
14400 if (pixel->widget_context != (GC) NULL)
14401 (void) XFreeGC(display,pixel->widget_context);
14402 pixel->widget_context=XCreateGC(display,windows->context.id,context_mask,
14403 &context_values);
14404 if (pixel->widget_context == (GC) NULL)
14405 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14406 display_image->filename);
14407 context_values.background=pixel->foreground_color.pixel;
14408 context_values.foreground=pixel->background_color.pixel;
14409 context_values.plane_mask=context_values.background ^
14410 context_values.foreground;
14411 if (pixel->highlight_context != (GC) NULL)
14412 (void) XFreeGC(display,pixel->highlight_context);
14413 pixel->highlight_context=XCreateGC(display,windows->context.id,
14414 (unsigned long) (context_mask | GCPlaneMask),&context_values);
14415 if (pixel->highlight_context == (GC) NULL)
14416 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14417 display_image->filename);
14418 (void) XDestroyWindow(display,windows->context.id);
14419
14420
14421
14422 XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL,
14423 icon_resources,&windows->icon);
14424 windows->icon.geometry=resource_info->icon_geometry;
14425 XBestIconSize(display,&windows->icon,display_image);
14426 windows->icon.attributes.colormap=XDefaultColormap(display,
14427 icon_visual->screen);
14428 windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask;
14429 (void) CloneString(&class_hints->res_name,"icon");
14430 manager_hints->flags=InputHint | StateHint;
14431 manager_hints->input=MagickFalse;
14432 manager_hints->initial_state=IconicState;
14433 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14434 &windows->icon);
14435 if (display_image->debug != MagickFalse)
14436 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)",
14437 windows->icon.id);
14438
14439
14440
14441 if (icon_pixel->annotate_context != (GC) NULL)
14442 (void) XFreeGC(display,icon_pixel->annotate_context);
14443 context_values.background=icon_pixel->background_color.pixel;
14444 context_values.foreground=icon_pixel->foreground_color.pixel;
14445 icon_pixel->annotate_context=XCreateGC(display,windows->icon.id,
14446 (unsigned long) (GCBackground | GCForeground),&context_values);
14447 if (icon_pixel->annotate_context == (GC) NULL)
14448 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14449 display_image->filename);
14450 windows->icon.annotate_context=icon_pixel->annotate_context;
14451
14452
14453
14454 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14455 &windows->image);
14456 windows->image.shape=MagickTrue;
14457 if (resource_info->use_shared_memory == MagickFalse)
14458 windows->image.shared_memory=MagickFalse;
14459 if ((resource_info->title != (char *) NULL) && !(*state & MontageImageState))
14460 {
14461 char
14462 *title;
14463
14464 title=InterpretImageProperties(resource_info->image_info,display_image,
14465 resource_info->title);
14466 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
14467 (void) CopyMagickString(windows->image.icon_name,title,MaxTextExtent);
14468 title=DestroyString(title);
14469 }
14470 else
14471 {
14472 char
14473 filename[MaxTextExtent];
14474
14475
14476
14477
14478 GetPathComponent(display_image->magick_filename,TailPath,filename);
14479 if (GetImageListLength(display_image) == 1)
14480 (void) FormatMagickString(windows->image.name,MaxTextExtent,
14481 "ImageMagick: %s",filename);
14482 else
14483 (void) FormatMagickString(windows->image.name,MaxTextExtent,
14484 "ImageMagick: %s[%lu of %lu]",filename,display_image->scene,
14485 GetImageListLength(display_image));
14486 (void) CopyMagickString(windows->image.icon_name,filename,MaxTextExtent);
14487 }
14488 if (resource_info->immutable)
14489 windows->image.immutable=MagickTrue;
14490 windows->image.use_pixmap=resource_info->use_pixmap;
14491 windows->image.geometry=resource_info->image_geometry;
14492 (void) FormatMagickString(geometry,MaxTextExtent,"%ux%u+0+0>!",
14493 XDisplayWidth(display,visual_info->screen),
14494 XDisplayHeight(display,visual_info->screen));
14495 geometry_info.width=display_image->columns;
14496 geometry_info.height=display_image->rows;
14497 geometry_info.x=0;
14498 geometry_info.y=0;
14499 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
14500 &geometry_info.width,&geometry_info.height);
14501 windows->image.width=(unsigned int) geometry_info.width;
14502 windows->image.height=(unsigned int) geometry_info.height;
14503 windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14504 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14505 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14506 PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask;
14507 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14508 resource_info,&windows->backdrop);
14509 if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL))
14510 {
14511
14512
14513
14514 windows->backdrop.x=0;
14515 windows->backdrop.y=0;
14516 (void) CloneString(&windows->backdrop.name,"ImageMagick Backdrop");
14517 windows->backdrop.flags=(unsigned long) (USSize | USPosition);
14518 windows->backdrop.width=(unsigned int)
14519 XDisplayWidth(display,visual_info->screen);
14520 windows->backdrop.height=(unsigned int)
14521 XDisplayHeight(display,visual_info->screen);
14522 windows->backdrop.border_width=0;
14523 windows->backdrop.immutable=MagickTrue;
14524 windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask |
14525 ButtonReleaseMask;
14526 windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask |
14527 StructureNotifyMask;
14528 (void) CloneString(&class_hints->res_name,"backdrop");
14529 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14530 manager_hints->icon_window=windows->icon.id;
14531 manager_hints->input=MagickTrue;
14532 manager_hints->initial_state=resource_info->iconic ? IconicState :
14533 NormalState;
14534 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14535 &windows->backdrop);
14536 if (display_image->debug != MagickFalse)
14537 (void) LogMagickEvent(X11Event,GetMagickModule(),
14538 "Window id: 0x%lx (backdrop)",windows->backdrop.id);
14539 (void) XMapWindow(display,windows->backdrop.id);
14540 (void) XClearWindow(display,windows->backdrop.id);
14541 if (windows->image.id != (Window) NULL)
14542 {
14543 (void) XDestroyWindow(display,windows->image.id);
14544 windows->image.id=(Window) NULL;
14545 }
14546
14547
14548
14549 windows->image.flags|=USPosition;
14550 windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)-
14551 (windows->image.width/2);
14552 windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)-
14553 (windows->image.height/2);
14554 }
14555 if (resource_info->name == (char *) NULL)
14556 (void) CloneString(&class_hints->res_name,resource_info->client_name);
14557 else
14558 (void) CloneString(&class_hints->res_name,resource_info->name);
14559 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14560 manager_hints->icon_window=windows->icon.id;
14561 manager_hints->input=MagickTrue;
14562 manager_hints->initial_state=resource_info->iconic ? IconicState :
14563 NormalState;
14564 if (windows->group_leader.id != (Window) NULL)
14565 {
14566
14567
14568
14569 manager_hints->flags|=WindowGroupHint;
14570 manager_hints->window_group=windows->group_leader.id;
14571 (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask);
14572 if (display_image->debug != MagickFalse)
14573 (void) LogMagickEvent(X11Event,GetMagickModule(),
14574 "Window id: 0x%lx (group leader)",windows->group_leader.id);
14575 }
14576 XMakeWindow(display,
14577 (Window) (resource_info->backdrop ? windows->backdrop.id : root_window),
14578 argv,argc,class_hints,manager_hints,&windows->image);
14579 (void) XChangeProperty(display,windows->image.id,windows->im_protocols,
14580 XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0);
14581 if (windows->group_leader.id != (Window) NULL)
14582 (void) XSetTransientForHint(display,windows->image.id,
14583 windows->group_leader.id);
14584 if (display_image->debug != MagickFalse)
14585 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)",
14586 windows->image.id);
14587
14588
14589
14590 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14591 &windows->info);
14592 (void) CloneString(&windows->info.name,"Info");
14593 (void) CloneString(&windows->info.icon_name,"Info");
14594 windows->info.border_width=1;
14595 windows->info.x=2;
14596 windows->info.y=2;
14597 windows->info.flags|=PPosition;
14598 windows->info.attributes.win_gravity=UnmapGravity;
14599 windows->info.attributes.event_mask=ButtonPressMask | ExposureMask |
14600 StructureNotifyMask;
14601 (void) CloneString(&class_hints->res_name,"info");
14602 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14603 manager_hints->input=MagickFalse;
14604 manager_hints->initial_state=NormalState;
14605 manager_hints->window_group=windows->image.id;
14606 XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints,
14607 &windows->info);
14608 windows->info.highlight_stipple=XCreateBitmapFromData(display,
14609 windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14610 windows->info.shadow_stipple=XCreateBitmapFromData(display,
14611 windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14612 (void) XSetTransientForHint(display,windows->info.id,windows->image.id);
14613 if (windows->image.mapped != MagickFalse)
14614 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
14615 if (display_image->debug != MagickFalse)
14616 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)",
14617 windows->info.id);
14618
14619
14620
14621 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14622 resource_info,&windows->command);
14623 windows->command.data=MagickMenus;
14624 (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL);
14625 (void) FormatMagickString(resource_name,MaxTextExtent,"%s.command",
14626 resource_info->client_name);
14627 windows->command.geometry=XGetResourceClass(resource_info->resource_database,
14628 resource_name,"geometry",(char *) NULL);
14629 (void) CloneString(&windows->command.name,MagickTitle);
14630 windows->command.border_width=0;
14631 windows->command.flags|=PPosition;
14632 windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14633 ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask |
14634 OwnerGrabButtonMask | StructureNotifyMask;
14635 (void) CloneString(&class_hints->res_name,"command");
14636 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14637 manager_hints->input=MagickTrue;
14638 manager_hints->initial_state=NormalState;
14639 manager_hints->window_group=windows->image.id;
14640 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14641 &windows->command);
14642 windows->command.highlight_stipple=XCreateBitmapFromData(display,
14643 windows->command.id,(char *) HighlightBitmap,HighlightWidth,
14644 HighlightHeight);
14645 windows->command.shadow_stipple=XCreateBitmapFromData(display,
14646 windows->command.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14647 (void) XSetTransientForHint(display,windows->command.id,windows->image.id);
14648 if (windows->command.mapped != MagickFalse)
14649 (void) XMapRaised(display,windows->command.id);
14650 if (display_image->debug != MagickFalse)
14651 (void) LogMagickEvent(X11Event,GetMagickModule(),
14652 "Window id: 0x%lx (command)",windows->command.id);
14653
14654
14655
14656 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14657 resource_info,&windows->widget);
14658 (void) FormatMagickString(resource_name,MaxTextExtent,"%s.widget",
14659 resource_info->client_name);
14660 windows->widget.geometry=XGetResourceClass(resource_info->resource_database,
14661 resource_name,"geometry",(char *) NULL);
14662 windows->widget.border_width=0;
14663 windows->widget.flags|=PPosition;
14664 windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14665 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14666 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14667 StructureNotifyMask;
14668 (void) CloneString(&class_hints->res_name,"widget");
14669 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14670 manager_hints->input=MagickTrue;
14671 manager_hints->initial_state=NormalState;
14672 manager_hints->window_group=windows->image.id;
14673 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14674 &windows->widget);
14675 windows->widget.highlight_stipple=XCreateBitmapFromData(display,
14676 windows->widget.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14677 windows->widget.shadow_stipple=XCreateBitmapFromData(display,
14678 windows->widget.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14679 (void) XSetTransientForHint(display,windows->widget.id,windows->image.id);
14680 if (display_image->debug != MagickFalse)
14681 (void) LogMagickEvent(X11Event,GetMagickModule(),
14682 "Window id: 0x%lx (widget)",windows->widget.id);
14683
14684
14685
14686 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14687 resource_info,&windows->popup);
14688 windows->popup.border_width=0;
14689 windows->popup.flags|=PPosition;
14690 windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14691 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14692 KeyReleaseMask | LeaveWindowMask | StructureNotifyMask;
14693 (void) CloneString(&class_hints->res_name,"popup");
14694 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14695 manager_hints->input=MagickTrue;
14696 manager_hints->initial_state=NormalState;
14697 manager_hints->window_group=windows->image.id;
14698 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14699 &windows->popup);
14700 windows->popup.highlight_stipple=XCreateBitmapFromData(display,
14701 windows->popup.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14702 windows->popup.shadow_stipple=XCreateBitmapFromData(display,
14703 windows->popup.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14704 (void) XSetTransientForHint(display,windows->popup.id,windows->image.id);
14705 if (display_image->debug != MagickFalse)
14706 (void) LogMagickEvent(X11Event,GetMagickModule(),
14707 "Window id: 0x%lx (pop up)",windows->popup.id);
14708
14709
14710
14711 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14712 resource_info,&windows->magnify);
14713 if (resource_info->use_shared_memory == MagickFalse)
14714 windows->magnify.shared_memory=MagickFalse;
14715 (void) FormatMagickString(resource_name,MaxTextExtent,"%s.magnify",
14716 resource_info->client_name);
14717 windows->magnify.geometry=XGetResourceClass(resource_info->resource_database,
14718 resource_name,"geometry",(char *) NULL);
14719 (void) FormatMagickString(windows->magnify.name,MaxTextExtent,"Magnify %uX",
14720 resource_info->magnify);
14721 if (windows->magnify.cursor != (Cursor) NULL)
14722 (void) XFreeCursor(display,windows->magnify.cursor);
14723 windows->magnify.cursor=XMakeCursor(display,windows->image.id,
14724 map_info->colormap,resource_info->background_color,
14725 resource_info->foreground_color);
14726 if (windows->magnify.cursor == (Cursor) NULL)
14727 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateCursor",
14728 display_image->filename);
14729 windows->magnify.width=MagnifySize;
14730 windows->magnify.height=MagnifySize;
14731 windows->magnify.flags|=PPosition;
14732 windows->magnify.min_width=MagnifySize;
14733 windows->magnify.min_height=MagnifySize;
14734 windows->magnify.width_inc=MagnifySize;
14735 windows->magnify.height_inc=MagnifySize;
14736 windows->magnify.data=resource_info->magnify;
14737 windows->magnify.attributes.cursor=windows->magnify.cursor;
14738 windows->magnify.attributes.event_mask=ButtonPressMask | ButtonReleaseMask |
14739 ExposureMask | KeyPressMask | KeyReleaseMask | OwnerGrabButtonMask |
14740 StructureNotifyMask;
14741 (void) CloneString(&class_hints->res_name,"magnify");
14742 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14743 manager_hints->input=MagickTrue;
14744 manager_hints->initial_state=NormalState;
14745 manager_hints->window_group=windows->image.id;
14746 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14747 &windows->magnify);
14748 if (display_image->debug != MagickFalse)
14749 (void) LogMagickEvent(X11Event,GetMagickModule(),
14750 "Window id: 0x%lx (magnify)",windows->magnify.id);
14751 (void) XSetTransientForHint(display,windows->magnify.id,windows->image.id);
14752
14753
14754
14755 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14756 resource_info,&windows->pan);
14757 (void) CloneString(&windows->pan.name,"Pan Icon");
14758 windows->pan.width=windows->icon.width;
14759 windows->pan.height=windows->icon.height;
14760 (void) FormatMagickString(resource_name,MaxTextExtent,"%s.pan",
14761 resource_info->client_name);
14762 windows->pan.geometry=XGetResourceClass(resource_info->resource_database,
14763 resource_name,"geometry",(char *) NULL);
14764 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
14765 &windows->pan.width,&windows->pan.height);
14766 windows->pan.flags|=PPosition;
14767 windows->pan.immutable=MagickTrue;
14768 windows->pan.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14769 ButtonReleaseMask | ExposureMask | KeyPressMask | KeyReleaseMask |
14770 StructureNotifyMask;
14771 (void) CloneString(&class_hints->res_name,"pan");
14772 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14773 manager_hints->input=MagickFalse;
14774 manager_hints->initial_state=NormalState;
14775 manager_hints->window_group=windows->image.id;
14776 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14777 &windows->pan);
14778 if (display_image->debug != MagickFalse)
14779 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (pan)",
14780 windows->pan.id);
14781 (void) XSetTransientForHint(display,windows->pan.id,windows->image.id);
14782 if (windows->info.mapped != MagickFalse)
14783 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
14784 if ((windows->image.mapped == MagickFalse) ||
14785 (windows->backdrop.id != (Window) NULL))
14786 (void) XMapWindow(display,windows->image.id);
14787
14788
14789
14790 if (warning_handler == (WarningHandler) NULL)
14791 {
14792 warning_handler=resource_info->display_warnings ?
14793 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
14794 warning_handler=resource_info->display_warnings ?
14795 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
14796 }
14797
14798
14799
14800 windows->image.x=0;
14801 windows->image.y=0;
14802 windows->magnify.shape=MagickFalse;
14803 width=(unsigned int) display_image->columns;
14804 height=(unsigned int) display_image->rows;
14805 if ((display_image->columns != width) || (display_image->rows != height))
14806 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
14807 display_image->filename);
14808 status=XMakeImage(display,resource_info,&windows->image,display_image,
14809 width,height);
14810 if (status == MagickFalse)
14811 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
14812 display_image->filename);
14813 status=XMakeImage(display,resource_info,&windows->magnify,(Image *) NULL,
14814 windows->magnify.width,windows->magnify.height);
14815 if (status == MagickFalse)
14816 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
14817 display_image->filename);
14818 if (windows->magnify.mapped != MagickFalse)
14819 (void) XMapRaised(display,windows->magnify.id);
14820 if (windows->pan.mapped != MagickFalse)
14821 (void) XMapRaised(display,windows->pan.id);
14822 windows->image.window_changes.width=(int) display_image->columns;
14823 windows->image.window_changes.height=(int) display_image->rows;
14824 (void) XConfigureImage(display,resource_info,windows,display_image);
14825 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
14826 (void) XSync(display,MagickFalse);
14827
14828
14829
14830 delay=display_image->delay/MagickMax(display_image->ticks_per_second,1L);
14831 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
14832 update_time=0;
14833 if (resource_info->update != MagickFalse)
14834 {
14835 MagickBooleanType
14836 status;
14837
14838
14839
14840
14841 status=GetPathAttributes(display_image->filename,&attributes);
14842 if (status != MagickFalse)
14843 update_time=attributes.st_mtime;
14844 }
14845 *state&=(~FormerImageState);
14846 *state&=(~MontageImageState);
14847 *state&=(~NextImageState);
14848 do
14849 {
14850
14851
14852
14853 if (windows->image.mapped != MagickFalse)
14854 if ((display_image->delay != 0) || (resource_info->update != 0))
14855 {
14856 if (timer < time((time_t *) NULL))
14857 {
14858 if (resource_info->update == MagickFalse)
14859 *state|=ExitState;
14860 else
14861 {
14862 MagickBooleanType
14863 status;
14864
14865
14866
14867
14868 status=GetPathAttributes(display_image->filename,&attributes);
14869 if (status != MagickFalse)
14870 if (update_time != attributes.st_mtime)
14871 {
14872
14873
14874
14875 (void) FormatMagickString(
14876 resource_info->image_info->filename,MaxTextExtent,
14877 "%s:%s",display_image->magick,
14878 display_image->filename);
14879 nexus=ReadImage(resource_info->image_info,
14880 &display_image->exception);
14881 if (nexus != (Image *) NULL)
14882 {
14883 nexus=DestroyImage(nexus);
14884 *state|=NextImageState | ExitState;
14885 }
14886 }
14887 delay=display_image->delay/MagickMax(
14888 display_image->ticks_per_second,1L);
14889 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
14890 }
14891 }
14892 if (XEventsQueued(display,QueuedAfterFlush) == 0)
14893 {
14894
14895
14896
14897 XDelay(display,SuspendTime << 2);
14898 continue;
14899 }
14900 }
14901 timestamp=time((time_t *) NULL);
14902 (void) XNextEvent(display,&event);
14903 if (windows->image.stasis == MagickFalse)
14904 windows->image.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
14905 MagickTrue : MagickFalse;
14906 if (windows->magnify.stasis == MagickFalse)
14907 windows->magnify.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
14908 MagickTrue : MagickFalse;
14909 if (event.xany.window == windows->command.id)
14910 {
14911
14912
14913
14914 id=XCommandWidget(display,windows,CommandMenu,&event);
14915 if (id < 0)
14916 continue;
14917 (void) CopyMagickString(command,CommandMenu[id],MaxTextExtent);
14918 command_type=CommandMenus[id];
14919 if (id < MagickMenus)
14920 {
14921
14922
14923
14924 entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id],
14925 command);
14926 if (entry < 0)
14927 continue;
14928 (void) CopyMagickString(command,Menus[id][entry],MaxTextExtent);
14929 command_type=Commands[id][entry];
14930 }
14931 if (command_type != NullCommand)
14932 nexus=XMagickCommand(display,resource_info,windows,command_type,
14933 &display_image);
14934 continue;
14935 }
14936 switch (event.type)
14937 {
14938 case ButtonPress:
14939 {
14940 if (display_image->debug != MagickFalse)
14941 (void) LogMagickEvent(X11Event,GetMagickModule(),
14942 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
14943 event.xbutton.button,event.xbutton.x,event.xbutton.y);
14944 if ((event.xbutton.button == Button3) &&
14945 (event.xbutton.state & Mod1Mask))
14946 {
14947
14948
14949
14950 event.xbutton.button=Button2;
14951 event.xbutton.state&=(~Mod1Mask);
14952 }
14953 if (event.xbutton.window == windows->backdrop.id)
14954 {
14955 (void) XSetInputFocus(display,event.xbutton.window,RevertToParent,
14956 event.xbutton.time);
14957 break;
14958 }
14959 if (event.xbutton.window == windows->image.id)
14960 {
14961 switch (event.xbutton.button)
14962 {
14963 case Button1:
14964 {
14965 if (resource_info->immutable)
14966 {
14967
14968
14969
14970 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
14971 command);
14972 if (entry >= 0)
14973 nexus=XMagickCommand(display,resource_info,windows,
14974 VirtualCommands[entry],&display_image);
14975 break;
14976 }
14977
14978
14979
14980 if (windows->command.mapped != MagickFalse)
14981 (void) XWithdrawWindow(display,windows->command.id,
14982 windows->command.screen);
14983 else
14984 {
14985 (void) XCommandWidget(display,windows,CommandMenu,
14986 (XEvent *) NULL);
14987 (void) XMapRaised(display,windows->command.id);
14988 }
14989 break;
14990 }
14991 case Button2:
14992 {
14993
14994
14995
14996 (void) XMagickCommand(display,resource_info,windows,ZoomCommand,
14997 &display_image);
14998 XMagnifyImage(display,windows,&event);
14999 break;
15000 }
15001 case Button3:
15002 {
15003 if (resource_info->immutable)
15004 {
15005
15006
15007
15008 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
15009 command);
15010 if (entry >= 0)
15011 nexus=XMagickCommand(display,resource_info,windows,
15012 VirtualCommands[entry],&display_image);
15013 break;
15014 }
15015 if (display_image->montage != (char *) NULL)
15016 {
15017
15018
15019
15020 nexus=XTileImage(display,resource_info,windows,
15021 display_image,&event);
15022 if (nexus != (Image *) NULL)
15023 *state|=MontageImageState | NextImageState | ExitState;
15024 vid_info.x=windows->image.x;
15025 vid_info.y=windows->image.y;
15026 break;
15027 }
15028
15029
15030
15031 entry=XMenuWidget(display,windows,"Short Cuts",ShortCutsMenu,
15032 command);
15033 if (entry >= 0)
15034 nexus=XMagickCommand(display,resource_info,windows,
15035 ShortCutsCommands[entry],&display_image);
15036 break;
15037 }
15038 case Button4:
15039 {
15040
15041
15042
15043 XTranslateImage(display,windows,*image,XK_Up);
15044 break;
15045 }
15046 case Button5:
15047 {
15048
15049
15050
15051 XTranslateImage(display,windows,*image,XK_Down);
15052 break;
15053 }
15054 default:
15055 break;
15056 }
15057 break;
15058 }
15059 if (event.xbutton.window == windows->magnify.id)
15060 {
15061 int
15062 factor;
15063
15064 static const char
15065 *MagnifyMenu[] =
15066 {
15067 "2",
15068 "4",
15069 "5",
15070 "6",
15071 "7",
15072 "8",
15073 "9",
15074 "3",
15075 (char *) NULL,
15076 };
15077
15078 static KeySym
15079 MagnifyCommands[] =
15080 {
15081 XK_2,
15082 XK_4,
15083 XK_5,
15084 XK_6,
15085 XK_7,
15086 XK_8,
15087 XK_9,
15088 XK_3
15089 };
15090
15091
15092
15093
15094 factor=XMenuWidget(display,windows,"Magnify",MagnifyMenu,command);
15095 if (factor >= 0)
15096 XMagnifyWindowCommand(display,windows,0,MagnifyCommands[factor]);
15097 break;
15098 }
15099 if (event.xbutton.window == windows->pan.id)
15100 {
15101 switch (event.xbutton.button)
15102 {
15103 case Button4:
15104 {
15105
15106
15107
15108 XTranslateImage(display,windows,*image,XK_Up);
15109 break;
15110 }
15111 case Button5:
15112 {
15113
15114
15115
15116 XTranslateImage(display,windows,*image,XK_Down);
15117 break;
15118 }
15119 default:
15120 {
15121 XPanImage(display,windows,&event);
15122 break;
15123 }
15124 }
15125 break;
15126 }
15127 delay=display_image->delay/MagickMax(display_image->ticks_per_second,
15128 1L);
15129 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15130 break;
15131 }
15132 case ButtonRelease:
15133 {
15134 if (display_image->debug != MagickFalse)
15135 (void) LogMagickEvent(X11Event,GetMagickModule(),
15136 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
15137 event.xbutton.button,event.xbutton.x,event.xbutton.y);
15138 break;
15139 }
15140 case ClientMessage:
15141 {
15142 if (display_image->debug != MagickFalse)
15143 (void) LogMagickEvent(X11Event,GetMagickModule(),
15144 "Client Message: 0x%lx 0x%lx %d 0x%lx",event.xclient.window,
15145 event.xclient.message_type,event.xclient.format,(unsigned long)
15146 event.xclient.data.l[0]);
15147 if (event.xclient.message_type == windows->im_protocols)
15148 {
15149 if (*event.xclient.data.l == (long) windows->im_update_widget)
15150 {
15151 (void) CloneString(&windows->command.name,MagickTitle);
15152 windows->command.data=MagickMenus;
15153 (void) XCommandWidget(display,windows,CommandMenu,
15154 (XEvent *) NULL);
15155 break;
15156 }
15157 if (*event.xclient.data.l == (long) windows->im_update_colormap)
15158 {
15159
15160
15161
15162 for (i=0; i < (int) number_windows; i++)
15163 {
15164 if (magick_windows[i]->id == windows->icon.id)
15165 continue;
15166 context_values.background=pixel->background_color.pixel;
15167 context_values.foreground=pixel->foreground_color.pixel;
15168 (void) XChangeGC(display,magick_windows[i]->annotate_context,
15169 context_mask,&context_values);
15170 (void) XChangeGC(display,magick_windows[i]->widget_context,
15171 context_mask,&context_values);
15172 context_values.background=pixel->foreground_color.pixel;
15173 context_values.foreground=pixel->background_color.pixel;
15174 context_values.plane_mask=context_values.background ^
15175 context_values.foreground;
15176 (void) XChangeGC(display,magick_windows[i]->highlight_context,
15177 (unsigned long) (context_mask | GCPlaneMask),
15178 &context_values);
15179 magick_windows[i]->attributes.background_pixel=
15180 pixel->background_color.pixel;
15181 magick_windows[i]->attributes.border_pixel=
15182 pixel->border_color.pixel;
15183 magick_windows[i]->attributes.colormap=map_info->colormap;
15184 (void) XChangeWindowAttributes(display,magick_windows[i]->id,
15185 magick_windows[i]->mask,&magick_windows[i]->attributes);
15186 }
15187 if (windows->pan.mapped != MagickFalse)
15188 {
15189 (void) XSetWindowBackgroundPixmap(display,windows->pan.id,
15190 windows->pan.pixmap);
15191 (void) XClearWindow(display,windows->pan.id);
15192 XDrawPanRectangle(display,windows);
15193 }
15194 if (windows->backdrop.id != (Window) NULL)
15195 (void) XInstallColormap(display,map_info->colormap);
15196 break;
15197 }
15198 if (*event.xclient.data.l == (long) windows->im_former_image)
15199 {
15200 *state|=FormerImageState | ExitState;
15201 break;
15202 }
15203 if (*event.xclient.data.l == (long) windows->im_next_image)
15204 {
15205 *state|=NextImageState | ExitState;
15206 break;
15207 }
15208 if (*event.xclient.data.l == (long) windows->im_retain_colors)
15209 {
15210 *state|=RetainColorsState;
15211 break;
15212 }
15213 if (*event.xclient.data.l == (long) windows->im_exit)
15214 {
15215 *state|=ExitState;
15216 break;
15217 }
15218 break;
15219 }
15220 if (event.xclient.message_type == windows->dnd_protocols)
15221 {
15222 Atom
15223 selection,
15224 type;
15225
15226 int
15227 format,
15228 status;
15229
15230 unsigned char
15231 *data;
15232
15233 unsigned long
15234 after,
15235 length;
15236
15237
15238
15239
15240 if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128))
15241 break;
15242 selection=XInternAtom(display,"DndSelection",MagickFalse);
15243 status=XGetWindowProperty(display,root_window,selection,0L,(long)
15244 MaxTextExtent,MagickFalse,(Atom) AnyPropertyType,&type,&format,
15245 &length,&after,&data);
15246 if ((status != Success) || (length == 0))
15247 break;
15248 if (*event.xclient.data.l == 2)
15249 {
15250
15251
15252
15253 (void) CopyMagickString(resource_info->image_info->filename,
15254 (char *) data,MaxTextExtent);
15255 }
15256 else
15257 {
15258
15259
15260
15261 if (strncmp((char *) data, "file:", 5) != 0)
15262 {
15263 (void) XFree((void *) data);
15264 break;
15265 }
15266 (void) CopyMagickString(resource_info->image_info->filename,
15267 ((char *) data)+5,MaxTextExtent);
15268 }
15269 nexus=ReadImage(resource_info->image_info,
15270 &display_image->exception);
15271 CatchException(&display_image->exception);
15272 if (nexus != (Image *) NULL)
15273 *state|=NextImageState | ExitState;
15274 (void) XFree((void *) data);
15275 break;
15276 }
15277
15278
15279
15280 if (event.xclient.message_type != windows->wm_protocols)
15281 break;
15282 if (*event.xclient.data.l != (long) windows->wm_delete_window)
15283 break;
15284 (void) XWithdrawWindow(display,event.xclient.window,
15285 visual_info->screen);
15286 if (event.xclient.window == windows->image.id)
15287 {
15288 *state|=ExitState;
15289 break;
15290 }
15291 if (event.xclient.window == windows->pan.id)
15292 {
15293
15294
15295
15296 windows->image.window_changes.width=windows->image.ximage->width;
15297 windows->image.window_changes.height=windows->image.ximage->height;
15298 (void) XConfigureImage(display,resource_info,windows,
15299 display_image);
15300 }
15301 break;
15302 }
15303 case ConfigureNotify:
15304 {
15305 if (display_image->debug != MagickFalse)
15306 (void) LogMagickEvent(X11Event,GetMagickModule(),
15307 "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window,
15308 event.xconfigure.width,event.xconfigure.height,event.xconfigure.x,
15309 event.xconfigure.y,event.xconfigure.send_event);
15310 if (event.xconfigure.window == windows->image.id)
15311 {
15312
15313
15314
15315 if (event.xconfigure.send_event != 0)
15316 {
15317 XWindowChanges
15318 window_changes;
15319
15320
15321
15322
15323 if (windows->command.geometry == (char *) NULL)
15324 if (windows->command.mapped == MagickFalse)
15325 {
15326 windows->command.x=event.xconfigure.x-
15327 windows->command.width-25;
15328 windows->command.y=event.xconfigure.y;
15329 XConstrainWindowPosition(display,&windows->command);
15330 window_changes.x=windows->command.x;
15331 window_changes.y=windows->command.y;
15332 (void) XReconfigureWMWindow(display,windows->command.id,
15333 windows->command.screen,(unsigned int) (CWX | CWY),
15334 &window_changes);
15335 }
15336 if (windows->widget.geometry == (char *) NULL)
15337 if (windows->widget.mapped == MagickFalse)
15338 {
15339 windows->widget.x=event.xconfigure.x+
15340 event.xconfigure.width/10;
15341 windows->widget.y=event.xconfigure.y+
15342 event.xconfigure.height/10;
15343 XConstrainWindowPosition(display,&windows->widget);
15344 window_changes.x=windows->widget.x;
15345 window_changes.y=windows->widget.y;
15346 (void) XReconfigureWMWindow(display,windows->widget.id,
15347 windows->widget.screen,(unsigned int) (CWX | CWY),
15348 &window_changes);
15349 }
15350 if (windows->magnify.geometry == (char *) NULL)
15351 if (windows->magnify.mapped == MagickFalse)
15352 {
15353 windows->magnify.x=event.xconfigure.x+
15354 event.xconfigure.width+25;
15355 windows->magnify.y=event.xconfigure.y;
15356 XConstrainWindowPosition(display,&windows->magnify);
15357 window_changes.x=windows->magnify.x;
15358 window_changes.y=windows->magnify.y;
15359 (void) XReconfigureWMWindow(display,windows->magnify.id,
15360 windows->magnify.screen,(unsigned int) (CWX | CWY),
15361 &window_changes);
15362 }
15363 if (windows->pan.geometry == (char *) NULL)
15364 if (windows->pan.mapped == MagickFalse)
15365 {
15366 windows->pan.x=event.xconfigure.x+
15367 event.xconfigure.width+25;
15368 windows->pan.y=event.xconfigure.y+
15369 windows->magnify.height+50;
15370 XConstrainWindowPosition(display,&windows->pan);
15371 window_changes.x=windows->pan.x;
15372 window_changes.y=windows->pan.y;
15373 (void) XReconfigureWMWindow(display,windows->pan.id,
15374 windows->pan.screen,(unsigned int) (CWX | CWY),
15375 &window_changes);
15376 }
15377 }
15378 if ((event.xconfigure.width == (long) windows->image.width) &&
15379 (event.xconfigure.height == (long) windows->image.height))
15380 break;
15381 windows->image.width=(unsigned int) event.xconfigure.width;
15382 windows->image.height=(unsigned int) event.xconfigure.height;
15383 windows->image.x=0;
15384 windows->image.y=0;
15385 if (display_image->montage != (char *) NULL)
15386 {
15387 windows->image.x=vid_info.x;
15388 windows->image.y=vid_info.y;
15389 }
15390
15391
15392
15393 if ((event.xconfigure.width < windows->image.ximage->width) ||
15394 (event.xconfigure.height < windows->image.ximage->height))
15395 {
15396 (void) XMapRaised(display,windows->pan.id);
15397 XDrawPanRectangle(display,windows);
15398 }
15399 else
15400 if (windows->pan.mapped != MagickFalse)
15401 (void) XWithdrawWindow(display,windows->pan.id,
15402 windows->pan.screen);
15403 break;
15404 }
15405 if (event.xconfigure.window == windows->magnify.id)
15406 {
15407 unsigned int
15408 magnify;
15409
15410
15411
15412
15413 windows->magnify.width=(unsigned int) event.xconfigure.width;
15414 windows->magnify.height=(unsigned int) event.xconfigure.height;
15415 if (windows->magnify.mapped == MagickFalse)
15416 break;
15417 magnify=1;
15418 while ((int) magnify <= event.xconfigure.width)
15419 magnify<<=1;
15420 while ((int) magnify <= event.xconfigure.height)
15421 magnify<<=1;
15422 magnify>>=1;
15423 if (((int) magnify != event.xconfigure.width) ||
15424 ((int) magnify != event.xconfigure.height))
15425 {
15426 window_changes.width=(int) magnify;
15427 window_changes.height=(int) magnify;
15428 (void) XReconfigureWMWindow(display,windows->magnify.id,
15429 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
15430 &window_changes);
15431 break;
15432 }
15433 if ((windows->magnify.mapped != MagickFalse) &&
15434 (windows->magnify.stasis != MagickFalse))
15435 {
15436 status=XMakeImage(display,resource_info,&windows->magnify,
15437 display_image,windows->magnify.width,windows->magnify.height);
15438 XMakeMagnifyImage(display,windows);
15439 }
15440 break;
15441 }
15442 if ((windows->magnify.mapped != MagickFalse) &&
15443 (event.xconfigure.window == windows->pan.id))
15444 {
15445
15446
15447
15448 if (event.xconfigure.send_event != 0)
15449 {
15450 windows->pan.x=event.xconfigure.x;
15451 windows->pan.y=event.xconfigure.y;
15452 }
15453 windows->pan.width=(unsigned int) event.xconfigure.width;
15454 windows->pan.height=(unsigned int) event.xconfigure.height;
15455 break;
15456 }
15457 if (event.xconfigure.window == windows->icon.id)
15458 {
15459
15460
15461
15462 windows->icon.width=(unsigned int) event.xconfigure.width;
15463 windows->icon.height=(unsigned int) event.xconfigure.height;
15464 break;
15465 }
15466 break;
15467 }
15468 case DestroyNotify:
15469 {
15470
15471
15472
15473 if (display_image->debug != MagickFalse)
15474 (void) LogMagickEvent(X11Event,GetMagickModule(),
15475 "Destroy Notify: 0x%lx",event.xdestroywindow.window);
15476 if (event.xdestroywindow.window == windows->group_leader.id)
15477 {
15478 *state|=ExitState;
15479 break;
15480 }
15481 break;
15482 }
15483 case EnterNotify:
15484 {
15485
15486
15487
15488 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15489 if (event.xcrossing.mode != NotifyUngrab)
15490 XInstallColormap(display,map_info->colormap);
15491 break;
15492 }
15493 case Expose:
15494 {
15495 if (display_image->debug != MagickFalse)
15496 (void) LogMagickEvent(X11Event,GetMagickModule(),
15497 "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window,
15498 event.xexpose.width,event.xexpose.height,event.xexpose.x,
15499 event.xexpose.y);
15500
15501
15502
15503 if (event.xexpose.window == windows->image.id)
15504 if (windows->image.mapped != MagickFalse)
15505 {
15506 XRefreshWindow(display,&windows->image,&event);
15507 delay=display_image->delay/MagickMax(
15508 display_image->ticks_per_second,1L);
15509 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15510 break;
15511 }
15512 if (event.xexpose.window == windows->magnify.id)
15513 if (event.xexpose.count == 0)
15514 if (windows->magnify.mapped != MagickFalse)
15515 {
15516 XMakeMagnifyImage(display,windows);
15517 break;
15518 }
15519 if (event.xexpose.window == windows->pan.id)
15520 if (event.xexpose.count == 0)
15521 {
15522 XDrawPanRectangle(display,windows);
15523 break;
15524 }
15525 if (event.xexpose.window == windows->icon.id)
15526 if (event.xexpose.count == 0)
15527 {
15528 XRefreshWindow(display,&windows->icon,&event);
15529 break;
15530 }
15531 break;
15532 }
15533 case KeyPress:
15534 {
15535 int
15536 length;
15537
15538
15539
15540
15541 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
15542 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15543 *(command+length)='\0';
15544 if (display_image->debug != MagickFalse)
15545 (void) LogMagickEvent(X11Event,GetMagickModule(),
15546 "Key press: %d 0x%lx (%s)",event.xkey.state,(unsigned long)
15547 key_symbol,command);
15548 if (event.xkey.window == windows->image.id)
15549 {
15550 command_type=XImageWindowCommand(display,resource_info,windows,
15551 event.xkey.state,key_symbol,&display_image);
15552 if (command_type != NullCommand)
15553 nexus=XMagickCommand(display,resource_info,windows,command_type,
15554 &display_image);
15555 }
15556 if (event.xkey.window == windows->magnify.id)
15557 XMagnifyWindowCommand(display,windows,event.xkey.state,key_symbol);
15558 if (event.xkey.window == windows->pan.id)
15559 {
15560 if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
15561 (void) XWithdrawWindow(display,windows->pan.id,
15562 windows->pan.screen);
15563 else
15564 if ((key_symbol == XK_F1) || (key_symbol == XK_Help))
15565 XTextViewWidget(display,resource_info,windows,MagickFalse,
15566 "Help Viewer - Image Pan",ImagePanHelp);
15567 else
15568 XTranslateImage(display,windows,*image,key_symbol);
15569 }
15570 delay=display_image->delay/MagickMax(
15571 display_image->ticks_per_second,1L);
15572 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15573 break;
15574 }
15575 case KeyRelease:
15576 {
15577
15578
15579
15580 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
15581 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15582 if (display_image->debug != MagickFalse)
15583 (void) LogMagickEvent(X11Event,GetMagickModule(),
15584 "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command);
15585 break;
15586 }
15587 case LeaveNotify:
15588 {
15589
15590
15591
15592 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15593 if (event.xcrossing.mode != NotifyUngrab)
15594 XUninstallColormap(display,map_info->colormap);
15595 break;
15596 }
15597 case MapNotify:
15598 {
15599 if (display_image->debug != MagickFalse)
15600 (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx",
15601 event.xmap.window);
15602 if (event.xmap.window == windows->backdrop.id)
15603 {
15604 (void) XSetInputFocus(display,event.xmap.window,RevertToParent,
15605 CurrentTime);
15606 windows->backdrop.mapped=MagickTrue;
15607 break;
15608 }
15609 if (event.xmap.window == windows->image.id)
15610 {
15611 if (windows->backdrop.id != (Window) NULL)
15612 (void) XInstallColormap(display,map_info->colormap);
15613 if (LocaleCompare(display_image->magick,"LOGO") == 0)
15614 {
15615 if (LocaleCompare(display_image->filename,"LOGO") == 0)
15616 nexus=XOpenImage(display,resource_info,windows,MagickFalse);
15617 }
15618 if (((int) windows->image.width < windows->image.ximage->width) ||
15619 ((int) windows->image.height < windows->image.ximage->height))
15620 (void) XMapRaised(display,windows->pan.id);
15621 windows->image.mapped=MagickTrue;
15622 break;
15623 }
15624 if (event.xmap.window == windows->magnify.id)
15625 {
15626 XMakeMagnifyImage(display,windows);
15627 windows->magnify.mapped=MagickTrue;
15628 (void) XWithdrawWindow(display,windows->info.id,
15629 windows->info.screen);
15630 break;
15631 }
15632 if (event.xmap.window == windows->pan.id)
15633 {
15634 XMakePanImage(display,resource_info,windows,display_image);
15635 windows->pan.mapped=MagickTrue;
15636 break;
15637 }
15638 if (event.xmap.window == windows->info.id)
15639 {
15640 windows->info.mapped=MagickTrue;
15641 break;
15642 }
15643 if (event.xmap.window == windows->icon.id)
15644 {
15645 MagickBooleanType
15646 taint;
15647
15648
15649
15650
15651 taint=display_image->taint;
15652 XMakeStandardColormap(display,icon_visual,icon_resources,
15653 display_image,icon_map,icon_pixel);
15654 (void) XMakeImage(display,icon_resources,&windows->icon,
15655 display_image,windows->icon.width,windows->icon.height);
15656 display_image->taint=taint;
15657 (void) XSetWindowBackgroundPixmap(display,windows->icon.id,
15658 windows->icon.pixmap);
15659 (void) XClearWindow(display,windows->icon.id);
15660 (void) XWithdrawWindow(display,windows->info.id,
15661 windows->info.screen);
15662 windows->icon.mapped=MagickTrue;
15663 break;
15664 }
15665 if (event.xmap.window == windows->command.id)
15666 {
15667 windows->command.mapped=MagickTrue;
15668 break;
15669 }
15670 if (event.xmap.window == windows->popup.id)
15671 {
15672 windows->popup.mapped=MagickTrue;
15673 break;
15674 }
15675 if (event.xmap.window == windows->widget.id)
15676 {
15677 windows->widget.mapped=MagickTrue;
15678 break;
15679 }
15680 break;
15681 }
15682 case MappingNotify:
15683 {
15684 (void) XRefreshKeyboardMapping(&event.xmapping);
15685 break;
15686 }
15687 case NoExpose:
15688 break;
15689 case PropertyNotify:
15690 {
15691 Atom
15692 type;
15693
15694 int
15695 format,
15696 status;
15697
15698 unsigned char
15699 *data;
15700
15701 unsigned long
15702 after,
15703 length;
15704
15705 if (display_image->debug != MagickFalse)
15706 (void) LogMagickEvent(X11Event,GetMagickModule(),
15707 "Property Notify: 0x%lx 0x%lx %d",event.xproperty.window,
15708 event.xproperty.atom,event.xproperty.state);
15709 if (event.xproperty.atom != windows->im_remote_command)
15710 break;
15711
15712
15713
15714 status=XGetWindowProperty(display,event.xproperty.window,
15715 event.xproperty.atom,0L,(long) MaxTextExtent,MagickFalse,(Atom)
15716 AnyPropertyType,&type,&format,&length,&after,&data);
15717 if ((status != Success) || (length == 0))
15718 break;
15719 if (LocaleCompare((char *) data,"-quit") == 0)
15720 {
15721 XClientMessage(display,windows->image.id,windows->im_protocols,
15722 windows->im_exit,CurrentTime);
15723 (void) XFree((void *) data);
15724 break;
15725 }
15726 (void) CopyMagickString(resource_info->image_info->filename,
15727 (char *) data,MaxTextExtent);
15728 (void) XFree((void *) data);
15729 nexus=ReadImage(resource_info->image_info,&display_image->exception);
15730 CatchException(&display_image->exception);
15731 if (nexus != (Image *) NULL)
15732 *state|=NextImageState | ExitState;
15733 break;
15734 }
15735 case ReparentNotify:
15736 {
15737 if (display_image->debug != MagickFalse)
15738 (void) LogMagickEvent(X11Event,GetMagickModule(),
15739 "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent,
15740 event.xreparent.window);
15741 break;
15742 }
15743 case UnmapNotify:
15744 {
15745 if (display_image->debug != MagickFalse)
15746 (void) LogMagickEvent(X11Event,GetMagickModule(),
15747 "Unmap Notify: 0x%lx",event.xunmap.window);
15748 if (event.xunmap.window == windows->backdrop.id)
15749 {
15750 windows->backdrop.mapped=MagickFalse;
15751 break;
15752 }
15753 if (event.xunmap.window == windows->image.id)
15754 {
15755 windows->image.mapped=MagickFalse;
15756 break;
15757 }
15758 if (event.xunmap.window == windows->magnify.id)
15759 {
15760 windows->magnify.mapped=MagickFalse;
15761 break;
15762 }
15763 if (event.xunmap.window == windows->pan.id)
15764 {
15765 windows->pan.mapped=MagickFalse;
15766 break;
15767 }
15768 if (event.xunmap.window == windows->info.id)
15769 {
15770 windows->info.mapped=MagickFalse;
15771 break;
15772 }
15773 if (event.xunmap.window == windows->icon.id)
15774 {
15775 if (map_info->colormap == icon_map->colormap)
15776 XConfigureImageColormap(display,resource_info,windows,
15777 display_image);
15778 (void) XFreeStandardColormap(display,icon_visual,icon_map,
15779 icon_pixel);
15780 windows->icon.mapped=MagickFalse;
15781 break;
15782 }
15783 if (event.xunmap.window == windows->command.id)
15784 {
15785 windows->command.mapped=MagickFalse;
15786 break;
15787 }
15788 if (event.xunmap.window == windows->popup.id)
15789 {
15790 if (windows->backdrop.id != (Window) NULL)
15791 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
15792 CurrentTime);
15793 windows->popup.mapped=MagickFalse;
15794 break;
15795 }
15796 if (event.xunmap.window == windows->widget.id)
15797 {
15798 if (windows->backdrop.id != (Window) NULL)
15799 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
15800 CurrentTime);
15801 windows->widget.mapped=MagickFalse;
15802 break;
15803 }
15804 break;
15805 }
15806 default:
15807 {
15808 if (display_image->debug != MagickFalse)
15809 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
15810 event.type);
15811 break;
15812 }
15813 }
15814 }
15815 while (!(*state & ExitState));
15816 if ((*state & ExitState) == 0)
15817 (void) XMagickCommand(display,resource_info,windows,FreeBuffersCommand,
15818 &display_image);
15819 else
15820 if (resource_info->confirm_edit != MagickFalse)
15821 {
15822
15823
15824
15825 if ((resource_info->immutable == MagickFalse) &&
15826 (display_image->taint != MagickFalse))
15827 {
15828 int
15829 status;
15830
15831 status=XConfirmWidget(display,windows,"Your image changed.",
15832 "Do you want to save it");
15833 if (status == 0)
15834 *state&=(~ExitState);
15835 else
15836 if (status > 0)
15837 (void) XMagickCommand(display,resource_info,windows,SaveCommand,
15838 &display_image);
15839 }
15840 }
15841 if ((windows->visual_info->klass == GrayScale) ||
15842 (windows->visual_info->klass == PseudoColor) ||
15843 (windows->visual_info->klass == DirectColor))
15844 {
15845
15846
15847
15848 if (windows->info.mapped != MagickFalse)
15849 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
15850 if (windows->magnify.mapped != MagickFalse)
15851 (void) XWithdrawWindow(display,windows->magnify.id,
15852 windows->magnify.screen);
15853 if (windows->command.mapped != MagickFalse)
15854 (void) XWithdrawWindow(display,windows->command.id,
15855 windows->command.screen);
15856 }
15857 if (windows->pan.mapped != MagickFalse)
15858 (void) XWithdrawWindow(display,windows->pan.id,windows->pan.screen);
15859 if (resource_info->backdrop == MagickFalse)
15860 if (windows->backdrop.mapped)
15861 {
15862 (void) XWithdrawWindow(display,windows->backdrop.id,
15863 windows->backdrop.screen);
15864 (void) XDestroyWindow(display,windows->backdrop.id);
15865 windows->backdrop.id=(Window) NULL;
15866 (void) XWithdrawWindow(display,windows->image.id,
15867 windows->image.screen);
15868 (void) XDestroyWindow(display,windows->image.id);
15869 windows->image.id=(Window) NULL;
15870 }
15871 XSetCursorState(display,windows,MagickTrue);
15872 XCheckRefreshWindows(display,windows);
15873 if (((*state & FormerImageState) != 0) || ((*state & NextImageState) != 0))
15874 *state&=(~ExitState);
15875 if (*state & ExitState)
15876 {
15877
15878
15879
15880 (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel);
15881 if (resource_info->map_type == (char *) NULL)
15882 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
15883
15884
15885
15886 if (resource_info->copy_image != (Image *) NULL)
15887 {
15888 resource_info->copy_image=DestroyImage(resource_info->copy_image);
15889 resource_info->copy_image=NewImageList();
15890 }
15891 DestroyXResources();
15892 }
15893 (void) XSync(display,MagickFalse);
15894
15895
15896
15897 (void) SetErrorHandler(warning_handler);
15898 (void) SetWarningHandler(warning_handler);
15899
15900
15901
15902 cwd=getcwd(working_directory,MaxTextExtent);
15903 {
15904 int
15905 status;
15906
15907 status=chdir(resource_info->home_directory);
15908 if (status == -1)
15909 (void) ThrowMagickException(&display_image->exception,GetMagickModule(),
15910 FileOpenError,"UnableToOpenFile","%s",resource_info->home_directory);
15911 }
15912 *image=display_image;
15913 return(nexus);
15914 }
15915 #else
15916
15917
15918
15919
15920
15921
15922
15923
15924
15925
15926
15927
15928
15929
15930
15931
15932
15933
15934
15935
15936
15937
15938
15939
15940
15941
15942
15943
15944 MagickExport MagickBooleanType DisplayImages(const ImageInfo *image_info,
15945 Image *image)
15946 {
15947 assert(image_info != (const ImageInfo *) NULL);
15948 assert(image_info->signature == MagickSignature);
15949 assert(image != (Image *) NULL);
15950 assert(image->signature == MagickSignature);
15951 if (image->debug != MagickFalse)
15952 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
15953 (void) ThrowMagickException(&image->exception,GetMagickModule(),
15954 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (X11)",
15955 image->filename);
15956 return(MagickFalse);
15957 }
15958
15959
15960
15961
15962
15963
15964
15965
15966
15967
15968
15969
15970
15971
15972
15973
15974
15975
15976
15977
15978
15979
15980
15981
15982
15983
15984
15985
15986
15987
15988
15989 MagickExport MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
15990 const char *window,const char *filename,ExceptionInfo *exception)
15991 {
15992 assert(image_info != (const ImageInfo *) NULL);
15993 assert(image_info->signature == MagickSignature);
15994 assert(filename != (char *) NULL);
15995 (void) window;
15996 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
15997 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
15998 "DelegateLibrarySupportNotBuiltIn","`%s' (X11)",image_info->filename);
15999 return(MagickFalse);
16000 }
16001 #endif