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 "automagically 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 preceding",
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 preceding",
00812 " this command with a number. For example to display the",
00813 " third page preceding 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 if ((images->iterations != 0) && (i >= (long) images->iterations))
01673 break;
01674 image=GetImageFromList(images,i % GetImageListLength(images));
01675 (void) XDisplayImage(display,&resource_info,argv,1,&image,&state);
01676 }
01677 argv[0]=DestroyString(argv[0]);
01678 (void) XCloseDisplay(display);
01679 XDestroyResourceInfo(&resource_info);
01680 if (images->exception.severity != UndefinedException)
01681 return(MagickFalse);
01682 return(MagickTrue);
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
01714
01715 MagickExport MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
01716 const char *window,const char *filename,ExceptionInfo *exception)
01717 {
01718 Display
01719 *display;
01720
01721 MagickStatusType
01722 status;
01723
01724 assert(image_info != (const ImageInfo *) NULL);
01725 assert(image_info->signature == MagickSignature);
01726 assert(filename != (char *) NULL);
01727 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
01728 display=XOpenDisplay(image_info->server_name);
01729 if (display == (Display *) NULL)
01730 {
01731 (void) ThrowMagickException(exception,GetMagickModule(),XServerError,
01732 "UnableToOpenXServer","`%s'",XDisplayName(image_info->server_name));
01733 return(MagickFalse);
01734 }
01735 (void) XSetErrorHandler(XError);
01736 status=XRemoteCommand(display,window,filename);
01737 (void) XCloseDisplay(display);
01738 return(status != 0 ? MagickTrue : MagickFalse);
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
01772 static inline long MagickMax(const long x,const long y)
01773 {
01774 if (x > y)
01775 return(x);
01776 return(y);
01777 }
01778
01779 static inline long MagickMin(const long x,const long y)
01780 {
01781 if (x < y)
01782 return(x);
01783 return(y);
01784 }
01785
01786 static MagickBooleanType XAnnotateEditImage(Display *display,
01787 XResourceInfo *resource_info,XWindows *windows,Image *image)
01788 {
01789 static const char
01790 *AnnotateMenu[] =
01791 {
01792 "Font Name",
01793 "Font Color",
01794 "Box Color",
01795 "Rotate Text",
01796 "Help",
01797 "Dismiss",
01798 (char *) NULL
01799 },
01800 *TextMenu[] =
01801 {
01802 "Help",
01803 "Apply",
01804 (char *) NULL
01805 };
01806
01807 static const ModeType
01808 AnnotateCommands[] =
01809 {
01810 AnnotateNameCommand,
01811 AnnotateFontColorCommand,
01812 AnnotateBackgroundColorCommand,
01813 AnnotateRotateCommand,
01814 AnnotateHelpCommand,
01815 AnnotateDismissCommand
01816 },
01817 TextCommands[] =
01818 {
01819 TextHelpCommand,
01820 TextApplyCommand
01821 };
01822
01823 static MagickBooleanType
01824 transparent_box = MagickTrue,
01825 transparent_pen = MagickFalse;
01826
01827 static MagickRealType
01828 degrees = 0.0;
01829
01830 static unsigned int
01831 box_id = MaxNumberPens-2,
01832 font_id = 0,
01833 pen_id = 0;
01834
01835 char
01836 command[MaxTextExtent],
01837 text[MaxTextExtent];
01838
01839 const char
01840 *ColorMenu[MaxNumberPens+1];
01841
01842 Cursor
01843 cursor;
01844
01845 GC
01846 annotate_context;
01847
01848 int
01849 id,
01850 pen_number,
01851 status,
01852 x,
01853 y;
01854
01855 KeySym
01856 key_symbol;
01857
01858 register char
01859 *p;
01860
01861 register long
01862 i;
01863
01864 unsigned int
01865 height,
01866 width;
01867
01868 unsigned long
01869 state;
01870
01871 XAnnotateInfo
01872 *annotate_info,
01873 *previous_info;
01874
01875 XColor
01876 color;
01877
01878 XFontStruct
01879 *font_info;
01880
01881 XEvent
01882 event,
01883 text_event;
01884
01885
01886
01887
01888 (void) CloneString(&windows->command.name,"Annotate");
01889 windows->command.data=4;
01890 (void) XCommandWidget(display,windows,AnnotateMenu,(XEvent *) NULL);
01891 (void) XMapRaised(display,windows->command.id);
01892 XClientMessage(display,windows->image.id,windows->im_protocols,
01893 windows->im_update_widget,CurrentTime);
01894
01895
01896
01897 XQueryPosition(display,windows->image.id,&x,&y);
01898 (void) XSelectInput(display,windows->image.id,
01899 windows->image.attributes.event_mask | PointerMotionMask);
01900 cursor=XCreateFontCursor(display,XC_left_side);
01901 (void) XCheckDefineCursor(display,windows->image.id,cursor);
01902 state=DefaultState;
01903 do
01904 {
01905 if (windows->info.mapped != MagickFalse)
01906 {
01907
01908
01909
01910 (void) FormatMagickString(text,MaxTextExtent," %+d%+d ",
01911 x+windows->image.x,y+windows->image.y);
01912 XInfoWidget(display,windows,text);
01913 }
01914
01915
01916
01917 XScreenEvent(display,windows,&event);
01918 if (event.xany.window == windows->command.id)
01919 {
01920
01921
01922
01923 id=XCommandWidget(display,windows,AnnotateMenu,&event);
01924 (void) XCheckDefineCursor(display,windows->image.id,cursor);
01925 if (id < 0)
01926 continue;
01927 switch (AnnotateCommands[id])
01928 {
01929 case AnnotateNameCommand:
01930 {
01931 const char
01932 *FontMenu[MaxNumberFonts];
01933
01934 int
01935 font_number;
01936
01937
01938
01939
01940 for (i=0; i < MaxNumberFonts; i++)
01941 FontMenu[i]=resource_info->font_name[i];
01942 FontMenu[MaxNumberFonts-2]="Browser...";
01943 FontMenu[MaxNumberFonts-1]=(const char *) NULL;
01944
01945
01946
01947 font_number=XMenuWidget(display,windows,AnnotateMenu[id],
01948 (const char **) FontMenu,command);
01949 if (font_number < 0)
01950 break;
01951 if (font_number == (MaxNumberFonts-2))
01952 {
01953 static char
01954 font_name[MaxTextExtent] = "fixed";
01955
01956
01957
01958
01959 resource_info->font_name[font_number]=font_name;
01960 XFontBrowserWidget(display,windows,"Select",font_name);
01961 if (*font_name == '\0')
01962 break;
01963 }
01964
01965
01966
01967 font_info=XLoadQueryFont(display,resource_info->font_name[
01968 font_number]);
01969 if (font_info == (XFontStruct *) NULL)
01970 {
01971 XNoticeWidget(display,windows,"Unable to load font:",
01972 resource_info->font_name[font_number]);
01973 break;
01974 }
01975 font_id=(unsigned int) font_number;
01976 (void) XFreeFont(display,font_info);
01977 break;
01978 }
01979 case AnnotateFontColorCommand:
01980 {
01981
01982
01983
01984 for (i=0; i < (int) (MaxNumberPens-2); i++)
01985 ColorMenu[i]=resource_info->pen_colors[i];
01986 ColorMenu[MaxNumberPens-2]="transparent";
01987 ColorMenu[MaxNumberPens-1]="Browser...";
01988 ColorMenu[MaxNumberPens]=(const char *) NULL;
01989
01990
01991
01992 pen_number=XMenuWidget(display,windows,AnnotateMenu[id],
01993 (const char **) ColorMenu,command);
01994 if (pen_number < 0)
01995 break;
01996 transparent_pen=pen_number == (MaxNumberPens-2) ? MagickTrue :
01997 MagickFalse;
01998 if (transparent_pen != MagickFalse)
01999 break;
02000 if (pen_number == (MaxNumberPens-1))
02001 {
02002 static char
02003 color_name[MaxTextExtent] = "gray";
02004
02005
02006
02007
02008 resource_info->pen_colors[pen_number]=color_name;
02009 XColorBrowserWidget(display,windows,"Select",color_name);
02010 if (*color_name == '\0')
02011 break;
02012 }
02013
02014
02015
02016 (void) XParseColor(display,windows->map_info->colormap,
02017 resource_info->pen_colors[pen_number],&color);
02018 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
02019 (unsigned int) MaxColors,&color);
02020 windows->pixel_info->pen_colors[pen_number]=color;
02021 pen_id=(unsigned int) pen_number;
02022 break;
02023 }
02024 case AnnotateBackgroundColorCommand:
02025 {
02026
02027
02028
02029 for (i=0; i < (int) (MaxNumberPens-2); i++)
02030 ColorMenu[i]=resource_info->pen_colors[i];
02031 ColorMenu[MaxNumberPens-2]="transparent";
02032 ColorMenu[MaxNumberPens-1]="Browser...";
02033 ColorMenu[MaxNumberPens]=(const char *) NULL;
02034
02035
02036
02037 pen_number=XMenuWidget(display,windows,AnnotateMenu[id],
02038 (const char **) ColorMenu,command);
02039 if (pen_number < 0)
02040 break;
02041 transparent_box=pen_number == (MaxNumberPens-2) ? MagickTrue :
02042 MagickFalse;
02043 if (transparent_box != MagickFalse)
02044 break;
02045 if (pen_number == (MaxNumberPens-1))
02046 {
02047 static char
02048 color_name[MaxTextExtent] = "gray";
02049
02050
02051
02052
02053 resource_info->pen_colors[pen_number]=color_name;
02054 XColorBrowserWidget(display,windows,"Select",color_name);
02055 if (*color_name == '\0')
02056 break;
02057 }
02058
02059
02060
02061 (void) XParseColor(display,windows->map_info->colormap,
02062 resource_info->pen_colors[pen_number],&color);
02063 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
02064 (unsigned int) MaxColors,&color);
02065 windows->pixel_info->pen_colors[pen_number]=color;
02066 box_id=(unsigned int) pen_number;
02067 break;
02068 }
02069 case AnnotateRotateCommand:
02070 {
02071 int
02072 entry;
02073
02074 static char
02075 angle[MaxTextExtent] = "30.0";
02076
02077 static const char
02078 *RotateMenu[] =
02079 {
02080 "-90",
02081 "-45",
02082 "-30",
02083 "0",
02084 "30",
02085 "45",
02086 "90",
02087 "180",
02088 "Dialog...",
02089 (char *) NULL,
02090 };
02091
02092
02093
02094
02095 entry=XMenuWidget(display,windows,AnnotateMenu[id],RotateMenu,
02096 command);
02097 if (entry < 0)
02098 break;
02099 if (entry != 8)
02100 {
02101 degrees=atof(RotateMenu[entry]);
02102 break;
02103 }
02104 (void) XDialogWidget(display,windows,"OK","Enter rotation angle:",
02105 angle);
02106 if (*angle == '\0')
02107 break;
02108 degrees=atof(angle);
02109 break;
02110 }
02111 case AnnotateHelpCommand:
02112 {
02113 XTextViewWidget(display,resource_info,windows,MagickFalse,
02114 "Help Viewer - Image Annotation",ImageAnnotateHelp);
02115 break;
02116 }
02117 case AnnotateDismissCommand:
02118 {
02119
02120
02121
02122 state|=EscapeState;
02123 state|=ExitState;
02124 break;
02125 }
02126 default:
02127 break;
02128 }
02129 continue;
02130 }
02131 switch (event.type)
02132 {
02133 case ButtonPress:
02134 {
02135 if (event.xbutton.button != Button1)
02136 break;
02137 if (event.xbutton.window != windows->image.id)
02138 break;
02139
02140
02141
02142 x=event.xbutton.x;
02143 y=event.xbutton.y;
02144 state|=ExitState;
02145 break;
02146 }
02147 case ButtonRelease:
02148 break;
02149 case Expose:
02150 break;
02151 case KeyPress:
02152 {
02153 if (event.xkey.window != windows->image.id)
02154 break;
02155
02156
02157
02158 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
02159 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
02160 switch ((int) key_symbol)
02161 {
02162 case XK_Escape:
02163 case XK_F20:
02164 {
02165
02166
02167
02168 state|=EscapeState;
02169 state|=ExitState;
02170 break;
02171 }
02172 case XK_F1:
02173 case XK_Help:
02174 {
02175 XTextViewWidget(display,resource_info,windows,MagickFalse,
02176 "Help Viewer - Image Annotation",ImageAnnotateHelp);
02177 break;
02178 }
02179 default:
02180 {
02181 (void) XBell(display,0);
02182 break;
02183 }
02184 }
02185 break;
02186 }
02187 case MotionNotify:
02188 {
02189
02190
02191
02192 x=event.xmotion.x;
02193 y=event.xmotion.y;
02194 if (windows->info.mapped != MagickFalse)
02195 {
02196 if ((x < (int) (windows->info.x+windows->info.width)) &&
02197 (y < (int) (windows->info.y+windows->info.height)))
02198 (void) XWithdrawWindow(display,windows->info.id,
02199 windows->info.screen);
02200 }
02201 else
02202 if ((x > (int) (windows->info.x+windows->info.width)) ||
02203 (y > (int) (windows->info.y+windows->info.height)))
02204 (void) XMapWindow(display,windows->info.id);
02205 break;
02206 }
02207 default:
02208 break;
02209 }
02210 } while ((state & ExitState) == 0);
02211 (void) XSelectInput(display,windows->image.id,
02212 windows->image.attributes.event_mask);
02213 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
02214 if ((state & EscapeState) != 0)
02215 return(MagickTrue);
02216
02217
02218
02219 font_info=XLoadQueryFont(display,resource_info->font_name[font_id]);
02220 if (font_info == (XFontStruct *) NULL)
02221 {
02222 XNoticeWidget(display,windows,"Unable to load font:",
02223 resource_info->font_name[font_id]);
02224 font_info=windows->font_info;
02225 }
02226 if ((x+font_info->max_bounds.width) >= (int) windows->image.width)
02227 x=(int) windows->image.width-font_info->max_bounds.width;
02228 if (y < (int) (font_info->ascent+font_info->descent))
02229 y=(int) font_info->ascent+font_info->descent;
02230 if (((int) font_info->max_bounds.width > (int) windows->image.width) ||
02231 ((font_info->ascent+font_info->descent) >= (int) windows->image.height))
02232 return(MagickFalse);
02233
02234
02235
02236 annotate_info=(XAnnotateInfo *) AcquireMagickMemory(sizeof(*annotate_info));
02237 if (annotate_info == (XAnnotateInfo *) NULL)
02238 return(MagickFalse);
02239 XGetAnnotateInfo(annotate_info);
02240 annotate_info->x=x;
02241 annotate_info->y=y;
02242 if ((transparent_box == MagickFalse) && (transparent_pen == MagickFalse))
02243 annotate_info->stencil=OpaqueStencil;
02244 else
02245 if (transparent_box == MagickFalse)
02246 annotate_info->stencil=BackgroundStencil;
02247 else
02248 annotate_info->stencil=ForegroundStencil;
02249 annotate_info->height=(unsigned int) font_info->ascent+font_info->descent;
02250 annotate_info->degrees=degrees;
02251 annotate_info->font_info=font_info;
02252 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
02253 windows->image.width/MagickMax(font_info->min_bounds.width,1)+2UL,
02254 sizeof(*annotate_info->text));
02255 if (annotate_info->text == (char *) NULL)
02256 return(MagickFalse);
02257
02258
02259
02260 cursor=XCreateFontCursor(display,XC_pencil);
02261 (void) XCheckDefineCursor(display,windows->image.id,cursor);
02262 annotate_context=windows->image.annotate_context;
02263 (void) XSetFont(display,annotate_context,font_info->fid);
02264 (void) XSetBackground(display,annotate_context,
02265 windows->pixel_info->pen_colors[box_id].pixel);
02266 (void) XSetForeground(display,annotate_context,
02267 windows->pixel_info->pen_colors[pen_id].pixel);
02268
02269
02270
02271 (void) CloneString(&windows->command.name,"Text");
02272 windows->command.data=0;
02273 (void) XCommandWidget(display,windows,TextMenu,(XEvent *) NULL);
02274 state=DefaultState;
02275 (void) XDrawString(display,windows->image.id,annotate_context,x,y,"_",1);
02276 text_event.xexpose.width=(int) font_info->max_bounds.width;
02277 text_event.xexpose.height=font_info->max_bounds.ascent+
02278 font_info->max_bounds.descent;
02279 p=annotate_info->text;
02280 do
02281 {
02282
02283
02284
02285 *p='\0';
02286 (void) XDrawString(display,windows->image.id,annotate_context,x,y,"_",1);
02287
02288
02289
02290 XScreenEvent(display,windows,&event);
02291 if (event.xany.window == windows->command.id)
02292 {
02293
02294
02295
02296 (void) XSetBackground(display,annotate_context,
02297 windows->pixel_info->background_color.pixel);
02298 (void) XSetForeground(display,annotate_context,
02299 windows->pixel_info->foreground_color.pixel);
02300 id=XCommandWidget(display,windows,AnnotateMenu,&event);
02301 (void) XSetBackground(display,annotate_context,
02302 windows->pixel_info->pen_colors[box_id].pixel);
02303 (void) XSetForeground(display,annotate_context,
02304 windows->pixel_info->pen_colors[pen_id].pixel);
02305 if (id < 0)
02306 continue;
02307 switch (TextCommands[id])
02308 {
02309 case TextHelpCommand:
02310 {
02311 XTextViewWidget(display,resource_info,windows,MagickFalse,
02312 "Help Viewer - Image Annotation",ImageAnnotateHelp);
02313 (void) XCheckDefineCursor(display,windows->image.id,cursor);
02314 break;
02315 }
02316 case TextApplyCommand:
02317 {
02318
02319
02320
02321 annotate_info->width=(unsigned int) XTextWidth(font_info,
02322 annotate_info->text,(int) strlen(annotate_info->text));
02323 XRefreshWindow(display,&windows->image,&text_event);
02324 state|=ExitState;
02325 break;
02326 }
02327 default:
02328 break;
02329 }
02330 continue;
02331 }
02332
02333
02334
02335 text_event.xexpose.x=x;
02336 text_event.xexpose.y=y-font_info->max_bounds.ascent;
02337 (void) XClearArea(display,windows->image.id,x,text_event.xexpose.y,
02338 (unsigned int) text_event.xexpose.width,(unsigned int)
02339 text_event.xexpose.height,MagickFalse);
02340 XRefreshWindow(display,&windows->image,&text_event);
02341 switch (event.type)
02342 {
02343 case ButtonPress:
02344 {
02345 if (event.xbutton.window != windows->image.id)
02346 break;
02347 if (event.xbutton.button == Button2)
02348 {
02349
02350
02351
02352 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
02353 windows->image.id,CurrentTime);
02354 break;
02355 }
02356 break;
02357 }
02358 case Expose:
02359 {
02360 if (event.xexpose.count == 0)
02361 {
02362 XAnnotateInfo
02363 *text_info;
02364
02365
02366
02367
02368 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
02369 text_info=annotate_info;
02370 while (text_info != (XAnnotateInfo *) NULL)
02371 {
02372 if (annotate_info->stencil == ForegroundStencil)
02373 (void) XDrawString(display,windows->image.id,annotate_context,
02374 text_info->x,text_info->y,text_info->text,
02375 (int) strlen(text_info->text));
02376 else
02377 (void) XDrawImageString(display,windows->image.id,
02378 annotate_context,text_info->x,text_info->y,text_info->text,
02379 (int) strlen(text_info->text));
02380 text_info=text_info->previous;
02381 }
02382 (void) XDrawString(display,windows->image.id,annotate_context,
02383 x,y,"_",1);
02384 }
02385 break;
02386 }
02387 case KeyPress:
02388 {
02389 int
02390 length;
02391
02392 if (event.xkey.window != windows->image.id)
02393 break;
02394
02395
02396
02397 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
02398 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
02399 *(command+length)='\0';
02400 if (((event.xkey.state & ControlMask) != 0) ||
02401 ((event.xkey.state & Mod1Mask) != 0))
02402 state|=ModifierState;
02403 if ((state & ModifierState) != 0)
02404 switch ((int) key_symbol)
02405 {
02406 case XK_u:
02407 case XK_U:
02408 {
02409 key_symbol=DeleteCommand;
02410 break;
02411 }
02412 default:
02413 break;
02414 }
02415 switch ((int) key_symbol)
02416 {
02417 case XK_BackSpace:
02418 {
02419
02420
02421
02422 if (p == annotate_info->text)
02423 {
02424 if (annotate_info->previous == (XAnnotateInfo *) NULL)
02425 break;
02426 else
02427 {
02428
02429
02430
02431 annotate_info=annotate_info->previous;
02432 p=annotate_info->text;
02433 x=annotate_info->x+annotate_info->width;
02434 y=annotate_info->y;
02435 if (annotate_info->width != 0)
02436 p+=strlen(annotate_info->text);
02437 break;
02438 }
02439 }
02440 p--;
02441 x-=XTextWidth(font_info,p,1);
02442 text_event.xexpose.x=x;
02443 text_event.xexpose.y=y-font_info->max_bounds.ascent;
02444 XRefreshWindow(display,&windows->image,&text_event);
02445 break;
02446 }
02447 case XK_bracketleft:
02448 {
02449 key_symbol=XK_Escape;
02450 break;
02451 }
02452 case DeleteCommand:
02453 {
02454
02455
02456
02457 while (p != annotate_info->text)
02458 {
02459 p--;
02460 x-=XTextWidth(font_info,p,1);
02461 text_event.xexpose.x=x;
02462 XRefreshWindow(display,&windows->image,&text_event);
02463 }
02464 break;
02465 }
02466 case XK_Escape:
02467 case XK_F20:
02468 {
02469
02470
02471
02472 annotate_info->width=(unsigned int) XTextWidth(font_info,
02473 annotate_info->text,(int) strlen(annotate_info->text));
02474 XRefreshWindow(display,&windows->image,&text_event);
02475 state|=ExitState;
02476 break;
02477 }
02478 default:
02479 {
02480
02481
02482
02483 if ((state & ModifierState) != 0)
02484 break;
02485 if (*command == '\0')
02486 break;
02487 *p=(*command);
02488 if (annotate_info->stencil == ForegroundStencil)
02489 (void) XDrawString(display,windows->image.id,annotate_context,
02490 x,y,p,1);
02491 else
02492 (void) XDrawImageString(display,windows->image.id,
02493 annotate_context,x,y,p,1);
02494 x+=XTextWidth(font_info,p,1);
02495 p++;
02496 if ((x+font_info->max_bounds.width) < (int) windows->image.width)
02497 break;
02498 }
02499 case XK_Return:
02500 case XK_KP_Enter:
02501 {
02502
02503
02504
02505 *p='\0';
02506 annotate_info->width=(unsigned int) XTextWidth(font_info,
02507 annotate_info->text,(int) strlen(annotate_info->text));
02508 if (annotate_info->next != (XAnnotateInfo *) NULL)
02509 {
02510
02511
02512
02513 annotate_info=annotate_info->next;
02514 x=annotate_info->x;
02515 y=annotate_info->y;
02516 p=annotate_info->text;
02517 break;
02518 }
02519 annotate_info->next=(XAnnotateInfo *) AcquireMagickMemory(
02520 sizeof(*annotate_info->next));
02521 if (annotate_info->next == (XAnnotateInfo *) NULL)
02522 return(MagickFalse);
02523 *annotate_info->next=(*annotate_info);
02524 annotate_info->next->previous=annotate_info;
02525 annotate_info=annotate_info->next;
02526 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
02527 windows->image.width/MagickMax(font_info->min_bounds.width,1)+2UL,
02528 sizeof(*annotate_info->text));
02529 if (annotate_info->text == (char *) NULL)
02530 return(MagickFalse);
02531 annotate_info->y+=annotate_info->height;
02532 if (annotate_info->y > (int) windows->image.height)
02533 annotate_info->y=(int) annotate_info->height;
02534 annotate_info->next=(XAnnotateInfo *) NULL;
02535 x=annotate_info->x;
02536 y=annotate_info->y;
02537 p=annotate_info->text;
02538 break;
02539 }
02540 }
02541 break;
02542 }
02543 case KeyRelease:
02544 {
02545
02546
02547
02548 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
02549 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
02550 state&=(~ModifierState);
02551 break;
02552 }
02553 case SelectionNotify:
02554 {
02555 Atom
02556 type;
02557
02558 int
02559 format;
02560
02561 unsigned char
02562 *data;
02563
02564 unsigned long
02565 after,
02566 length;
02567
02568
02569
02570
02571 if (event.xselection.property == (Atom) None)
02572 break;
02573 status=XGetWindowProperty(display,event.xselection.requestor,
02574 event.xselection.property,0L,(long) MaxTextExtent,True,XA_STRING,
02575 &type,&format,&length,&after,&data);
02576 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
02577 (length == 0))
02578 break;
02579
02580
02581
02582 for (i=0; i < (long) length; i++)
02583 {
02584 if ((char) data[i] != '\n')
02585 {
02586
02587
02588
02589 *p=(char) data[i];
02590 (void) XDrawString(display,windows->image.id,annotate_context,
02591 x,y,p,1);
02592 x+=XTextWidth(font_info,p,1);
02593 p++;
02594 if ((x+font_info->max_bounds.width) < (int) windows->image.width)
02595 continue;
02596 }
02597
02598
02599
02600 *p='\0';
02601 annotate_info->width=(unsigned int) XTextWidth(font_info,
02602 annotate_info->text,(int) strlen(annotate_info->text));
02603 if (annotate_info->next != (XAnnotateInfo *) NULL)
02604 {
02605
02606
02607
02608 annotate_info=annotate_info->next;
02609 x=annotate_info->x;
02610 y=annotate_info->y;
02611 p=annotate_info->text;
02612 continue;
02613 }
02614 annotate_info->next=(XAnnotateInfo *) AcquireMagickMemory(
02615 sizeof(*annotate_info->next));
02616 if (annotate_info->next == (XAnnotateInfo *) NULL)
02617 return(MagickFalse);
02618 *annotate_info->next=(*annotate_info);
02619 annotate_info->next->previous=annotate_info;
02620 annotate_info=annotate_info->next;
02621 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
02622 windows->image.width/MagickMax(font_info->min_bounds.width,1)+2UL,
02623 sizeof(*annotate_info->text));
02624 if (annotate_info->text == (char *) NULL)
02625 return(MagickFalse);
02626 annotate_info->y+=annotate_info->height;
02627 if (annotate_info->y > (int) windows->image.height)
02628 annotate_info->y=(int) annotate_info->height;
02629 annotate_info->next=(XAnnotateInfo *) NULL;
02630 x=annotate_info->x;
02631 y=annotate_info->y;
02632 p=annotate_info->text;
02633 }
02634 (void) XFree((void *) data);
02635 break;
02636 }
02637 default:
02638 break;
02639 }
02640 } while ((state & ExitState) == 0);
02641 (void) XFreeCursor(display,cursor);
02642
02643
02644
02645 width=(unsigned int) image->columns;
02646 height=(unsigned int) image->rows;
02647 x=0;
02648 y=0;
02649 if (windows->image.crop_geometry != (char *) NULL)
02650 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
02651
02652
02653
02654 XSetCursorState(display,windows,MagickTrue);
02655 XCheckRefreshWindows(display,windows);
02656 while (annotate_info != (XAnnotateInfo *) NULL)
02657 {
02658 if (annotate_info->width == 0)
02659 {
02660
02661
02662
02663 previous_info=annotate_info->previous;
02664 annotate_info->text=(char *)
02665 RelinquishMagickMemory(annotate_info->text);
02666 annotate_info=(XAnnotateInfo *) RelinquishMagickMemory(annotate_info);
02667 annotate_info=previous_info;
02668 continue;
02669 }
02670
02671
02672
02673 windows->pixel_info->box_color=windows->pixel_info->pen_colors[box_id];
02674 if (windows->pixel_info->colors != 0)
02675 for (i=0; i < (long) windows->pixel_info->colors; i++)
02676 if (windows->pixel_info->pixels[i] ==
02677 windows->pixel_info->pen_colors[box_id].pixel)
02678 {
02679 windows->pixel_info->box_index=(unsigned short) i;
02680 break;
02681 }
02682 windows->pixel_info->pen_color=windows->pixel_info->pen_colors[pen_id];
02683 if (windows->pixel_info->colors != 0)
02684 for (i=0; i < (long) windows->pixel_info->colors; i++)
02685 if (windows->pixel_info->pixels[i] ==
02686 windows->pixel_info->pen_colors[pen_id].pixel)
02687 {
02688 windows->pixel_info->pen_index=(unsigned short) i;
02689 break;
02690 }
02691
02692
02693
02694 annotate_info->x=(int)
02695 width*(annotate_info->x+windows->image.x)/windows->image.ximage->width;
02696 annotate_info->y=(int) height*(annotate_info->y-font_info->ascent+
02697 windows->image.y)/windows->image.ximage->height;
02698 (void) FormatMagickString(annotate_info->geometry,MaxTextExtent,
02699 "%ux%u%+d%+d",width*annotate_info->width/windows->image.ximage->width,
02700 height*annotate_info->height/windows->image.ximage->height,
02701 annotate_info->x+x,annotate_info->y+y);
02702
02703
02704
02705 status=XAnnotateImage(display,windows->pixel_info,annotate_info,image);
02706 if (status == 0)
02707 return(MagickFalse);
02708
02709
02710
02711 previous_info=annotate_info->previous;
02712 annotate_info->text=DestroyString(annotate_info->text);
02713 annotate_info=(XAnnotateInfo *) RelinquishMagickMemory(annotate_info);
02714 annotate_info=previous_info;
02715 }
02716 (void) XSetForeground(display,annotate_context,
02717 windows->pixel_info->foreground_color.pixel);
02718 (void) XSetBackground(display,annotate_context,
02719 windows->pixel_info->background_color.pixel);
02720 (void) XSetFont(display,annotate_context,windows->font_info->fid);
02721 XSetCursorState(display,windows,MagickFalse);
02722 (void) XFreeFont(display,font_info);
02723
02724
02725
02726 XConfigureImageColormap(display,resource_info,windows,image);
02727 (void) XConfigureImage(display,resource_info,windows,image);
02728 return(MagickTrue);
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 static MagickBooleanType XChopImage(Display *display,
02829 XResourceInfo *resource_info,XWindows *windows,Image **image)
02830 {
02831 static const char
02832 *ChopMenu[] =
02833 {
02834 "Direction",
02835 "Help",
02836 "Dismiss",
02837 (char *) NULL
02838 };
02839
02840 static ModeType
02841 direction = HorizontalChopCommand;
02842
02843 static const ModeType
02844 ChopCommands[] =
02845 {
02846 ChopDirectionCommand,
02847 ChopHelpCommand,
02848 ChopDismissCommand
02849 },
02850 DirectionCommands[] =
02851 {
02852 HorizontalChopCommand,
02853 VerticalChopCommand
02854 };
02855
02856 char
02857 text[MaxTextExtent];
02858
02859 Image
02860 *chop_image;
02861
02862 int
02863 id,
02864 x,
02865 y;
02866
02867 MagickRealType
02868 scale_factor;
02869
02870 RectangleInfo
02871 chop_info;
02872
02873 unsigned int
02874 distance,
02875 height,
02876 width;
02877
02878 unsigned long
02879 state;
02880
02881 XEvent
02882 event;
02883
02884 XSegment
02885 segment_info;
02886
02887
02888
02889
02890 (void) CloneString(&windows->command.name,"Chop");
02891 windows->command.data=1;
02892 (void) XCommandWidget(display,windows,ChopMenu,(XEvent *) NULL);
02893 (void) XMapRaised(display,windows->command.id);
02894 XClientMessage(display,windows->image.id,windows->im_protocols,
02895 windows->im_update_widget,CurrentTime);
02896
02897
02898
02899 XQueryPosition(display,windows->image.id,&x,&y);
02900 (void) XSelectInput(display,windows->image.id,
02901 windows->image.attributes.event_mask | PointerMotionMask);
02902 state=DefaultState;
02903 do
02904 {
02905 if (windows->info.mapped != MagickFalse)
02906 {
02907
02908
02909
02910 (void) FormatMagickString(text,MaxTextExtent," %+d%+d ",
02911 x+windows->image.x,y+windows->image.y);
02912 XInfoWidget(display,windows,text);
02913 }
02914
02915
02916
02917 XScreenEvent(display,windows,&event);
02918 if (event.xany.window == windows->command.id)
02919 {
02920
02921
02922
02923 id=XCommandWidget(display,windows,ChopMenu,&event);
02924 if (id < 0)
02925 continue;
02926 switch (ChopCommands[id])
02927 {
02928 case ChopDirectionCommand:
02929 {
02930 char
02931 command[MaxTextExtent];
02932
02933 static const char
02934 *Directions[] =
02935 {
02936 "horizontal",
02937 "vertical",
02938 (char *) NULL,
02939 };
02940
02941
02942
02943
02944 id=XMenuWidget(display,windows,ChopMenu[id],Directions,command);
02945 if (id >= 0)
02946 direction=DirectionCommands[id];
02947 break;
02948 }
02949 case ChopHelpCommand:
02950 {
02951 XTextViewWidget(display,resource_info,windows,MagickFalse,
02952 "Help Viewer - Image Chop",ImageChopHelp);
02953 break;
02954 }
02955 case ChopDismissCommand:
02956 {
02957
02958
02959
02960 state|=EscapeState;
02961 state|=ExitState;
02962 break;
02963 }
02964 default:
02965 break;
02966 }
02967 continue;
02968 }
02969 switch (event.type)
02970 {
02971 case ButtonPress:
02972 {
02973 if (event.xbutton.button != Button1)
02974 break;
02975 if (event.xbutton.window != windows->image.id)
02976 break;
02977
02978
02979
02980 segment_info.x1=(short int) event.xbutton.x;
02981 segment_info.x2=(short int) event.xbutton.x;
02982 segment_info.y1=(short int) event.xbutton.y;
02983 segment_info.y2=(short int) event.xbutton.y;
02984 state|=ExitState;
02985 break;
02986 }
02987 case ButtonRelease:
02988 break;
02989 case Expose:
02990 break;
02991 case KeyPress:
02992 {
02993 char
02994 command[MaxTextExtent];
02995
02996 KeySym
02997 key_symbol;
02998
02999 if (event.xkey.window != windows->image.id)
03000 break;
03001
03002
03003
03004 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
03005 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
03006 switch ((int) key_symbol)
03007 {
03008 case XK_Escape:
03009 case XK_F20:
03010 {
03011
03012
03013
03014 state|=EscapeState;
03015 state|=ExitState;
03016 break;
03017 }
03018 case XK_F1:
03019 case XK_Help:
03020 {
03021 (void) XSetFunction(display,windows->image.highlight_context,
03022 GXcopy);
03023 XTextViewWidget(display,resource_info,windows,MagickFalse,
03024 "Help Viewer - Image Chop",ImageChopHelp);
03025 (void) XSetFunction(display,windows->image.highlight_context,
03026 GXinvert);
03027 break;
03028 }
03029 default:
03030 {
03031 (void) XBell(display,0);
03032 break;
03033 }
03034 }
03035 break;
03036 }
03037 case MotionNotify:
03038 {
03039
03040
03041
03042 x=event.xmotion.x;
03043 y=event.xmotion.y;
03044 if (windows->info.mapped != MagickFalse)
03045 {
03046 if ((x < (int) (windows->info.x+windows->info.width)) &&
03047 (y < (int) (windows->info.y+windows->info.height)))
03048 (void) XWithdrawWindow(display,windows->info.id,
03049 windows->info.screen);
03050 }
03051 else
03052 if ((x > (int) (windows->info.x+windows->info.width)) ||
03053 (y > (int) (windows->info.y+windows->info.height)))
03054 (void) XMapWindow(display,windows->info.id);
03055 }
03056 }
03057 } while ((state & ExitState) == 0);
03058 (void) XSelectInput(display,windows->image.id,
03059 windows->image.attributes.event_mask);
03060 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
03061 if ((state & EscapeState) != 0)
03062 return(MagickTrue);
03063
03064
03065
03066 chop_info.width=0;
03067 chop_info.height=0;
03068 chop_info.x=0;
03069 chop_info.y=0;
03070 distance=0;
03071 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
03072 state=DefaultState;
03073 do
03074 {
03075 if (distance > 9)
03076 {
03077
03078
03079
03080 if (windows->info.mapped == MagickFalse)
03081 (void) XMapWindow(display,windows->info.id);
03082 (void) FormatMagickString(text,MaxTextExtent," %lux%lu%+ld%+ld",
03083 chop_info.width,chop_info.height,chop_info.x,chop_info.y);
03084 XInfoWidget(display,windows,text);
03085 XHighlightLine(display,windows->image.id,
03086 windows->image.highlight_context,&segment_info);
03087 }
03088 else
03089 if (windows->info.mapped != MagickFalse)
03090 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
03091
03092
03093
03094 XScreenEvent(display,windows,&event);
03095 if (distance > 9)
03096 XHighlightLine(display,windows->image.id,
03097 windows->image.highlight_context,&segment_info);
03098 switch (event.type)
03099 {
03100 case ButtonPress:
03101 {
03102 segment_info.x2=(short int) event.xmotion.x;
03103 segment_info.y2=(short int) event.xmotion.y;
03104 break;
03105 }
03106 case ButtonRelease:
03107 {
03108
03109
03110
03111 segment_info.x2=(short int) event.xbutton.x;
03112 segment_info.y2=(short int) event.xbutton.y;
03113 state|=ExitState;
03114 break;
03115 }
03116 case Expose:
03117 break;
03118 case MotionNotify:
03119 {
03120 segment_info.x2=(short int) event.xmotion.x;
03121 segment_info.y2=(short int) event.xmotion.y;
03122 }
03123 default:
03124 break;
03125 }
03126
03127
03128
03129 if (segment_info.x2 < 0)
03130 segment_info.x2=0;
03131 else
03132 if (segment_info.x2 > windows->image.ximage->width)
03133 segment_info.x2=windows->image.ximage->width;
03134 if (segment_info.y2 < 0)
03135 segment_info.y2=0;
03136 else
03137 if (segment_info.y2 > windows->image.ximage->height)
03138 segment_info.y2=windows->image.ximage->height;
03139 distance=(unsigned int)
03140 (((segment_info.x2-segment_info.x1)*(segment_info.x2-segment_info.x1))+
03141 ((segment_info.y2-segment_info.y1)*(segment_info.y2-segment_info.y1)));
03142
03143
03144
03145 if (direction == HorizontalChopCommand)
03146 {
03147 chop_info.width=(unsigned long) (segment_info.x2-segment_info.x1+1);
03148 chop_info.x=windows->image.x+segment_info.x1;
03149 chop_info.height=0;
03150 chop_info.y=0;
03151 if (segment_info.x1 > (int) segment_info.x2)
03152 {
03153 chop_info.width=(unsigned long) (segment_info.x1-segment_info.x2+1);
03154 chop_info.x=windows->image.x+segment_info.x2;
03155 }
03156 }
03157 else
03158 {
03159 chop_info.width=0;
03160 chop_info.height=(unsigned long) (segment_info.y2-segment_info.y1+1);
03161 chop_info.x=0;
03162 chop_info.y=windows->image.y+segment_info.y1;
03163 if (segment_info.y1 > segment_info.y2)
03164 {
03165 chop_info.height=(unsigned long)
03166 (segment_info.y1-segment_info.y2+1);
03167 chop_info.y=windows->image.y+segment_info.y2;
03168 }
03169 }
03170 } while ((state & ExitState) == 0);
03171 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
03172 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
03173 if (distance <= 9)
03174 return(MagickTrue);
03175
03176
03177
03178 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image);
03179 XSetCursorState(display,windows,MagickTrue);
03180 XCheckRefreshWindows(display,windows);
03181 windows->image.window_changes.width=windows->image.ximage->width-
03182 (unsigned int) chop_info.width;
03183 windows->image.window_changes.height=windows->image.ximage->height-
03184 (unsigned int) chop_info.height;
03185 width=(unsigned int) (*image)->columns;
03186 height=(unsigned int) (*image)->rows;
03187 x=0;
03188 y=0;
03189 if (windows->image.crop_geometry != (char *) NULL)
03190 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
03191 scale_factor=(MagickRealType) width/windows->image.ximage->width;
03192 chop_info.x+=x;
03193 chop_info.x=(int) (scale_factor*chop_info.x+0.5);
03194 chop_info.width=(unsigned int) (scale_factor*chop_info.width+0.5);
03195 scale_factor=(MagickRealType) height/windows->image.ximage->height;
03196 chop_info.y+=y;
03197 chop_info.y=(int) (scale_factor*chop_info.y+0.5);
03198 chop_info.height=(unsigned int) (scale_factor*chop_info.height+0.5);
03199
03200
03201
03202 chop_image=ChopImage(*image,&chop_info,&(*image)->exception);
03203 XSetCursorState(display,windows,MagickFalse);
03204 if (chop_image == (Image *) NULL)
03205 return(MagickFalse);
03206 *image=DestroyImage(*image);
03207 *image=chop_image;
03208
03209
03210
03211 XConfigureImageColormap(display,resource_info,windows,*image);
03212 (void) XConfigureImage(display,resource_info,windows,*image);
03213 return(MagickTrue);
03214 }
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 static MagickBooleanType XColorEditImage(Display *display,
03250 XResourceInfo *resource_info,XWindows *windows,Image **image)
03251 {
03252 static const char
03253 *ColorEditMenu[] =
03254 {
03255 "Method",
03256 "Pixel Color",
03257 "Border Color",
03258 "Fuzz",
03259 "Undo",
03260 "Help",
03261 "Dismiss",
03262 (char *) NULL
03263 };
03264
03265 static const ModeType
03266 ColorEditCommands[] =
03267 {
03268 ColorEditMethodCommand,
03269 ColorEditColorCommand,
03270 ColorEditBorderCommand,
03271 ColorEditFuzzCommand,
03272 ColorEditUndoCommand,
03273 ColorEditHelpCommand,
03274 ColorEditDismissCommand
03275 };
03276
03277 static PaintMethod
03278 method = PointMethod;
03279
03280 static unsigned int
03281 pen_id = 0;
03282
03283 static XColor
03284 border_color = { 0, 0, 0, 0, 0, 0 };
03285
03286 char
03287 command[MaxTextExtent],
03288 text[MaxTextExtent];
03289
03290 Cursor
03291 cursor;
03292
03293 ExceptionInfo
03294 *exception;
03295
03296 int
03297 entry,
03298 id,
03299 x,
03300 x_offset,
03301 y,
03302 y_offset;
03303
03304 register PixelPacket
03305 *q;
03306
03307 register long
03308 i;
03309
03310 unsigned int
03311 height,
03312 width;
03313
03314 unsigned long
03315 state;
03316
03317 XColor
03318 color;
03319
03320 XEvent
03321 event;
03322
03323
03324
03325
03326 (void) CloneString(&windows->command.name,"Color Edit");
03327 windows->command.data=4;
03328 (void) XCommandWidget(display,windows,ColorEditMenu,(XEvent *) NULL);
03329 (void) XMapRaised(display,windows->command.id);
03330 XClientMessage(display,windows->image.id,windows->im_protocols,
03331 windows->im_update_widget,CurrentTime);
03332
03333
03334
03335 cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap,
03336 resource_info->background_color,resource_info->foreground_color);
03337 (void) XCheckDefineCursor(display,windows->image.id,cursor);
03338
03339
03340
03341 XQueryPosition(display,windows->image.id,&x,&y);
03342 (void) XSelectInput(display,windows->image.id,
03343 windows->image.attributes.event_mask | PointerMotionMask);
03344 state=DefaultState;
03345 do
03346 {
03347 if (windows->info.mapped != MagickFalse)
03348 {
03349
03350
03351
03352 (void) FormatMagickString(text,MaxTextExtent," %+d%+d ",
03353 x+windows->image.x,y+windows->image.y);
03354 XInfoWidget(display,windows,text);
03355 }
03356
03357
03358
03359 XScreenEvent(display,windows,&event);
03360 if (event.xany.window == windows->command.id)
03361 {
03362
03363
03364
03365 id=XCommandWidget(display,windows,ColorEditMenu,&event);
03366 if (id < 0)
03367 {
03368 (void) XCheckDefineCursor(display,windows->image.id,cursor);
03369 continue;
03370 }
03371 switch (ColorEditCommands[id])
03372 {
03373 case ColorEditMethodCommand:
03374 {
03375 char
03376 **methods;
03377
03378
03379
03380
03381 methods=(char **) GetMagickOptions(MagickMethodOptions);
03382 if (methods == (char **) NULL)
03383 break;
03384 entry=XMenuWidget(display,windows,ColorEditMenu[id],
03385 (const char **) methods,command);
03386 if (entry >= 0)
03387 method=(PaintMethod) ParseMagickOption(MagickMethodOptions,
03388 MagickFalse,methods[entry]);
03389 methods=DestroyStringList(methods);
03390 break;
03391 }
03392 case ColorEditColorCommand:
03393 {
03394 const char
03395 *ColorMenu[MaxNumberPens];
03396
03397 int
03398 pen_number;
03399
03400
03401
03402
03403 for (i=0; i < (int) (MaxNumberPens-2); i++)
03404 ColorMenu[i]=resource_info->pen_colors[i];
03405 ColorMenu[MaxNumberPens-2]="Browser...";
03406 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
03407
03408
03409
03410 pen_number=XMenuWidget(display,windows,ColorEditMenu[id],
03411 (const char **) ColorMenu,command);
03412 if (pen_number < 0)
03413 break;
03414 if (pen_number == (MaxNumberPens-2))
03415 {
03416 static char
03417 color_name[MaxTextExtent] = "gray";
03418
03419
03420
03421
03422 resource_info->pen_colors[pen_number]=color_name;
03423 XColorBrowserWidget(display,windows,"Select",color_name);
03424 if (*color_name == '\0')
03425 break;
03426 }
03427
03428
03429
03430 (void) XParseColor(display,windows->map_info->colormap,
03431 resource_info->pen_colors[pen_number],&color);
03432 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
03433 (unsigned int) MaxColors,&color);
03434 windows->pixel_info->pen_colors[pen_number]=color;
03435 pen_id=(unsigned int) pen_number;
03436 break;
03437 }
03438 case ColorEditBorderCommand:
03439 {
03440 const char
03441 *ColorMenu[MaxNumberPens];
03442
03443 int
03444 pen_number;
03445
03446
03447
03448
03449 for (i=0; i < (int) (MaxNumberPens-2); i++)
03450 ColorMenu[i]=resource_info->pen_colors[i];
03451 ColorMenu[MaxNumberPens-2]="Browser...";
03452 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
03453
03454
03455
03456 pen_number=XMenuWidget(display,windows,ColorEditMenu[id],
03457 (const char **) ColorMenu,command);
03458 if (pen_number < 0)
03459 break;
03460 if (pen_number == (MaxNumberPens-2))
03461 {
03462 static char
03463 color_name[MaxTextExtent] = "gray";
03464
03465
03466
03467
03468 resource_info->pen_colors[pen_number]=color_name;
03469 XColorBrowserWidget(display,windows,"Select",color_name);
03470 if (*color_name == '\0')
03471 break;
03472 }
03473
03474
03475
03476 (void) XParseColor(display,windows->map_info->colormap,
03477 resource_info->pen_colors[pen_number],&border_color);
03478 break;
03479 }
03480 case ColorEditFuzzCommand:
03481 {
03482 static char
03483 fuzz[MaxTextExtent];
03484
03485 static const char
03486 *FuzzMenu[] =
03487 {
03488 "0%",
03489 "2%",
03490 "5%",
03491 "10%",
03492 "15%",
03493 "Dialog...",
03494 (char *) NULL,
03495 };
03496
03497
03498
03499
03500 entry=XMenuWidget(display,windows,ColorEditMenu[id],FuzzMenu,
03501 command);
03502 if (entry < 0)
03503 break;
03504 if (entry != 5)
03505 {
03506 (*image)->fuzz=StringToDouble(FuzzMenu[entry],1.0*QuantumRange+
03507 1.0);
03508 break;
03509 }
03510 (void) (void) CopyMagickString(fuzz,"20%",MaxTextExtent);
03511 (void) XDialogWidget(display,windows,"Ok",
03512 "Enter fuzz factor (0.0 - 99.9%):",fuzz);
03513 if (*fuzz == '\0')
03514 break;
03515 (void) ConcatenateMagickString(fuzz,"%",MaxTextExtent);
03516 (*image)->fuzz=StringToDouble(fuzz,1.0*QuantumRange+1.0);
03517 break;
03518 }
03519 case ColorEditUndoCommand:
03520 {
03521 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
03522 image);
03523 break;
03524 }
03525 case ColorEditHelpCommand:
03526 default:
03527 {
03528 XTextViewWidget(display,resource_info,windows,MagickFalse,
03529 "Help Viewer - Image Annotation",ImageColorEditHelp);
03530 break;
03531 }
03532 case ColorEditDismissCommand:
03533 {
03534
03535
03536
03537 state|=EscapeState;
03538 state|=ExitState;
03539 break;
03540 }
03541 }
03542 (void) XCheckDefineCursor(display,windows->image.id,cursor);
03543 continue;
03544 }
03545 switch (event.type)
03546 {
03547 case ButtonPress:
03548 {
03549 if (event.xbutton.button != Button1)
03550 break;
03551 if ((event.xbutton.window != windows->image.id) &&
03552 (event.xbutton.window != windows->magnify.id))
03553 break;
03554
03555
03556
03557 x=event.xbutton.x;
03558 y=event.xbutton.y;
03559 (void) XMagickCommand(display,resource_info,windows,
03560 SaveToUndoBufferCommand,image);
03561 state|=UpdateConfigurationState;
03562 break;
03563 }
03564 case ButtonRelease:
03565 {
03566 if (event.xbutton.button != Button1)
03567 break;
03568 if ((event.xbutton.window != windows->image.id) &&
03569 (event.xbutton.window != windows->magnify.id))
03570 break;
03571
03572
03573
03574 x=event.xbutton.x;
03575 y=event.xbutton.y;
03576 XConfigureImageColormap(display,resource_info,windows,*image);
03577 (void) XConfigureImage(display,resource_info,windows,*image);
03578 XInfoWidget(display,windows,text);
03579 (void) XCheckDefineCursor(display,windows->image.id,cursor);
03580 state&=(~UpdateConfigurationState);
03581 break;
03582 }
03583 case Expose:
03584 break;
03585 case KeyPress:
03586 {
03587 KeySym
03588 key_symbol;
03589
03590 if (event.xkey.window == windows->magnify.id)
03591 {
03592 Window
03593 window;
03594
03595 window=windows->magnify.id;
03596 while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ;
03597 }
03598 if (event.xkey.window != windows->image.id)
03599 break;
03600
03601
03602
03603 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
03604 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
03605 switch ((int) key_symbol)
03606 {
03607 case XK_Escape:
03608 case XK_F20:
03609 {
03610
03611
03612
03613 state|=ExitState;
03614 break;
03615 }
03616 case XK_F1:
03617 case XK_Help:
03618 {
03619 XTextViewWidget(display,resource_info,windows,MagickFalse,
03620 "Help Viewer - Image Annotation",ImageColorEditHelp);
03621 break;
03622 }
03623 default:
03624 {
03625 (void) XBell(display,0);
03626 break;
03627 }
03628 }
03629 break;
03630 }
03631 case MotionNotify:
03632 {
03633
03634
03635
03636 x=event.xmotion.x;
03637 y=event.xmotion.y;
03638 if (windows->info.mapped != MagickFalse)
03639 {
03640 if ((x < (int) (windows->info.x+windows->info.width)) &&
03641 (y < (int) (windows->info.y+windows->info.height)))
03642 (void) XWithdrawWindow(display,windows->info.id,
03643 windows->info.screen);
03644 }
03645 else
03646 if ((x > (int) (windows->info.x+windows->info.width)) ||
03647 (y > (int) (windows->info.y+windows->info.height)))
03648 (void) XMapWindow(display,windows->info.id);
03649 break;
03650 }
03651 default:
03652 break;
03653 }
03654 if (event.xany.window == windows->magnify.id)
03655 {
03656 x=windows->magnify.x-windows->image.x;
03657 y=windows->magnify.y-windows->image.y;
03658 }
03659 x_offset=x;
03660 y_offset=y;
03661 if ((state & UpdateConfigurationState) != 0)
03662 {
03663 int
03664 x,
03665 y;
03666
03667
03668
03669
03670 (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1,
03671 MagickTrue);
03672 color=windows->pixel_info->pen_colors[pen_id];
03673 XPutPixel(windows->image.ximage,x_offset,y_offset,color.pixel);
03674 width=(unsigned int) (*image)->columns;
03675 height=(unsigned int) (*image)->rows;
03676 x=0;
03677 y=0;
03678 if (windows->image.crop_geometry != (char *) NULL)
03679 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
03680 &width,&height);
03681 x_offset=(int)
03682 (width*(windows->image.x+x_offset)/windows->image.ximage->width+x);
03683 y_offset=(int)
03684 (height*(windows->image.y+y_offset)/windows->image.ximage->height+y);
03685 if ((x_offset < 0) || (y_offset < 0))
03686 continue;
03687 if ((x_offset >= (long) (*image)->columns) ||
03688 (y_offset >= (long) (*image)->rows))
03689 continue;
03690 exception=(&(*image)->exception);
03691 switch (method)
03692 {
03693 case PointMethod:
03694 default:
03695 {
03696
03697
03698
03699 if (SetImageStorageClass(*image,DirectClass) == MagickFalse)
03700 return(MagickFalse);
03701 q=GetAuthenticPixels(*image,x_offset,y_offset,1,1,exception);
03702 if (q == (PixelPacket *) NULL)
03703 break;
03704 q->red=ScaleShortToQuantum(color.red);
03705 q->green=ScaleShortToQuantum(color.green);
03706 q->blue=ScaleShortToQuantum(color.blue);
03707 (void) SyncAuthenticPixels(*image,&(*image)->exception);
03708 break;
03709 }
03710 case ReplaceMethod:
03711 {
03712 PixelPacket
03713 target;
03714
03715
03716
03717
03718 (void) GetOneVirtualPixel(*image,x_offset,y_offset,&target,
03719 &(*image)->exception);
03720 if ((*image)->storage_class == DirectClass)
03721 {
03722 for (y=0; y < (long) (*image)->rows; y++)
03723 {
03724 q=GetAuthenticPixels(*image,0,y,(*image)->columns,1,exception);
03725 if (q == (PixelPacket *) NULL)
03726 break;
03727 for (x=0; x < (int) (*image)->columns; x++)
03728 {
03729 if (IsColorSimilar(*image,q,&target))
03730 {
03731 q->red=ScaleShortToQuantum(color.red);
03732 q->green=ScaleShortToQuantum(color.green);
03733 q->blue=ScaleShortToQuantum(color.blue);
03734 }
03735 q++;
03736 }
03737 if (SyncAuthenticPixels(*image,exception) == MagickFalse)
03738 break;
03739 }
03740 }
03741 else
03742 {
03743 for (i=0; i < (int) (*image)->colors; i++)
03744 if (IsColorSimilar(*image,(*image)->colormap+i,&target))
03745 {
03746 (*image)->colormap[i].red=ScaleShortToQuantum(color.red);
03747 (*image)->colormap[i].green=ScaleShortToQuantum(
03748 color.green);
03749 (*image)->colormap[i].blue=ScaleShortToQuantum(
03750 color.blue);
03751 }
03752 (void) SyncImage(*image);
03753 }
03754 break;
03755 }
03756 case FloodfillMethod:
03757 case FillToBorderMethod:
03758 {
03759 DrawInfo
03760 *draw_info;
03761
03762 MagickPixelPacket
03763 target;
03764
03765
03766
03767
03768 (void) GetOneVirtualMagickPixel(*image,x_offset,y_offset,&target,
03769 exception);
03770 if (method == FillToBorderMethod)
03771 {
03772 target.red=(MagickRealType)
03773 ScaleShortToQuantum(border_color.red);
03774 target.green=(MagickRealType)
03775 ScaleShortToQuantum(border_color.green);
03776 target.blue=(MagickRealType)
03777 ScaleShortToQuantum(border_color.blue);
03778 }
03779 draw_info=CloneDrawInfo(resource_info->image_info,
03780 (DrawInfo *) NULL);
03781 (void) QueryColorDatabase(resource_info->pen_colors[pen_id],
03782 &draw_info->fill,exception);
03783 (void) FloodfillPaintImage(*image,DefaultChannels,draw_info,&target,
03784 x_offset,y_offset,method == FloodfillMethod ? MagickFalse :
03785 MagickTrue);
03786 draw_info=DestroyDrawInfo(draw_info);
03787 break;
03788 }
03789 case ResetMethod:
03790 {
03791
03792
03793
03794 if (SetImageStorageClass(*image,DirectClass) == MagickFalse)
03795 return(MagickFalse);
03796 for (y=0; y < (long) (*image)->rows; y++)
03797 {
03798 q=QueueAuthenticPixels(*image,0,y,(*image)->columns,1,exception);
03799 if (q == (PixelPacket *) NULL)
03800 break;
03801 for (x=0; x < (int) (*image)->columns; x++)
03802 {
03803 q->red=ScaleShortToQuantum(color.red);
03804 q->green=ScaleShortToQuantum(color.green);
03805 q->blue=ScaleShortToQuantum(color.blue);
03806 q++;
03807 }
03808 if (SyncAuthenticPixels(*image,exception) == MagickFalse)
03809 break;
03810 }
03811 break;
03812 }
03813 }
03814 state&=(~UpdateConfigurationState);
03815 }
03816 } while ((state & ExitState) == 0);
03817 (void) XSelectInput(display,windows->image.id,
03818 windows->image.attributes.event_mask);
03819 XSetCursorState(display,windows,MagickFalse);
03820 (void) XFreeCursor(display,cursor);
03821 return(MagickTrue);
03822 }
03823
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 static MagickBooleanType XCompositeImage(Display *display,
03857 XResourceInfo *resource_info,XWindows *windows,Image *image)
03858 {
03859 static char
03860 displacement_geometry[MaxTextExtent] = "30x30",
03861 filename[MaxTextExtent] = "\0";
03862
03863 static const char
03864 *CompositeMenu[] =
03865 {
03866 "Operators",
03867 "Dissolve",
03868 "Displace",
03869 "Help",
03870 "Dismiss",
03871 (char *) NULL
03872 };
03873
03874 static CompositeOperator
03875 compose = CopyCompositeOp;
03876
03877 static const ModeType
03878 CompositeCommands[] =
03879 {
03880 CompositeOperatorsCommand,
03881 CompositeDissolveCommand,
03882 CompositeDisplaceCommand,
03883 CompositeHelpCommand,
03884 CompositeDismissCommand
03885 };
03886
03887 char
03888 text[MaxTextExtent];
03889
03890 Cursor
03891 cursor;
03892
03893 Image
03894 *composite_image;
03895
03896 int
03897 entry,
03898 id,
03899 x,
03900 y;
03901
03902 MagickRealType
03903 blend,
03904 scale_factor;
03905
03906 RectangleInfo
03907 highlight_info,
03908 composite_info;
03909
03910 unsigned int
03911 height,
03912 width;
03913
03914 unsigned long
03915 state;
03916
03917 XEvent
03918 event;
03919
03920
03921
03922
03923 XFileBrowserWidget(display,windows,"Composite",filename);
03924 if (*filename == '\0')
03925 return(MagickTrue);
03926
03927
03928
03929 XSetCursorState(display,windows,MagickTrue);
03930 XCheckRefreshWindows(display,windows);
03931 (void) CopyMagickString(resource_info->image_info->filename,filename,
03932 MaxTextExtent);
03933 composite_image=ReadImage(resource_info->image_info,&image->exception);
03934 CatchException(&image->exception);
03935 XSetCursorState(display,windows,MagickFalse);
03936 if (composite_image == (Image *) NULL)
03937 return(MagickFalse);
03938
03939
03940
03941 (void) CloneString(&windows->command.name,"Composite");
03942 windows->command.data=1;
03943 (void) XCommandWidget(display,windows,CompositeMenu,(XEvent *) NULL);
03944 (void) XMapRaised(display,windows->command.id);
03945 XClientMessage(display,windows->image.id,windows->im_protocols,
03946 windows->im_update_widget,CurrentTime);
03947
03948
03949
03950 XQueryPosition(display,windows->image.id,&x,&y);
03951 (void) XSelectInput(display,windows->image.id,
03952 windows->image.attributes.event_mask | PointerMotionMask);
03953 composite_info.x=windows->image.x+x;
03954 composite_info.y=windows->image.y+y;
03955 composite_info.width=0;
03956 composite_info.height=0;
03957 cursor=XCreateFontCursor(display,XC_ul_angle);
03958 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
03959 blend=0.0;
03960 state=DefaultState;
03961 do
03962 {
03963 if (windows->info.mapped != MagickFalse)
03964 {
03965
03966
03967
03968 (void) FormatMagickString(text,MaxTextExtent," %+ld%+ld ",
03969 composite_info.x,composite_info.y);
03970 XInfoWidget(display,windows,text);
03971 }
03972 highlight_info=composite_info;
03973 highlight_info.x=composite_info.x-windows->image.x;
03974 highlight_info.y=composite_info.y-windows->image.y;
03975 XHighlightRectangle(display,windows->image.id,
03976 windows->image.highlight_context,&highlight_info);
03977
03978
03979
03980 XScreenEvent(display,windows,&event);
03981 XHighlightRectangle(display,windows->image.id,
03982 windows->image.highlight_context,&highlight_info);
03983 if (event.xany.window == windows->command.id)
03984 {
03985
03986
03987
03988 id=XCommandWidget(display,windows,CompositeMenu,&event);
03989 if (id < 0)
03990 continue;
03991 switch (CompositeCommands[id])
03992 {
03993 case CompositeOperatorsCommand:
03994 {
03995 char
03996 command[MaxTextExtent],
03997 **operators;
03998
03999
04000
04001
04002 operators=GetMagickOptions(MagickComposeOptions);
04003 if (operators == (char **) NULL)
04004 break;
04005 entry=XMenuWidget(display,windows,CompositeMenu[id],
04006 (const char **) operators,command);
04007 if (entry >= 0)
04008 compose=(CompositeOperator) ParseMagickOption(
04009 MagickComposeOptions,MagickFalse,operators[entry]);
04010 operators=DestroyStringList(operators);
04011 break;
04012 }
04013 case CompositeDissolveCommand:
04014 {
04015 static char
04016 factor[MaxTextExtent] = "20.0";
04017
04018
04019
04020
04021 (void) XSetFunction(display,windows->image.highlight_context,
04022 GXcopy);
04023 (void) XDialogWidget(display,windows,"Dissolve",
04024 "Enter the blend factor (0.0 - 99.9%):",factor);
04025 (void) XSetFunction(display,windows->image.highlight_context,
04026 GXinvert);
04027 if (*factor == '\0')
04028 break;
04029 blend=atof(factor);
04030 compose=DissolveCompositeOp;
04031 break;
04032 }
04033 case CompositeDisplaceCommand:
04034 {
04035
04036
04037
04038 (void) XSetFunction(display,windows->image.highlight_context,
04039 GXcopy);
04040 (void) XDialogWidget(display,windows,"Displace",
04041 "Enter the horizontal and vertical scale:",displacement_geometry);
04042 (void) XSetFunction(display,windows->image.highlight_context,
04043 GXinvert);
04044 if (*displacement_geometry == '\0')
04045 break;
04046 compose=DisplaceCompositeOp;
04047 break;
04048 }
04049 case CompositeHelpCommand:
04050 {
04051 (void) XSetFunction(display,windows->image.highlight_context,
04052 GXcopy);
04053 XTextViewWidget(display,resource_info,windows,MagickFalse,
04054 "Help Viewer - Image Composite",ImageCompositeHelp);
04055 (void) XSetFunction(display,windows->image.highlight_context,
04056 GXinvert);
04057 break;
04058 }
04059 case CompositeDismissCommand:
04060 {
04061
04062
04063
04064 state|=EscapeState;
04065 state|=ExitState;
04066 break;
04067 }
04068 default:
04069 break;
04070 }
04071 continue;
04072 }
04073 switch (event.type)
04074 {
04075 case ButtonPress:
04076 {
04077 if (image->debug != MagickFalse)
04078 (void) LogMagickEvent(X11Event,GetMagickModule(),
04079 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
04080 event.xbutton.button,event.xbutton.x,event.xbutton.y);
04081 if (event.xbutton.button != Button1)
04082 break;
04083 if (event.xbutton.window != windows->image.id)
04084 break;
04085
04086
04087
04088 composite_info.width=composite_image->columns;
04089 composite_info.height=composite_image->rows;
04090 (void) XCheckDefineCursor(display,windows->image.id,cursor);
04091 composite_info.x=windows->image.x+event.xbutton.x;
04092 composite_info.y=windows->image.y+event.xbutton.y;
04093 break;
04094 }
04095 case ButtonRelease:
04096 {
04097 if (image->debug != MagickFalse)
04098 (void) LogMagickEvent(X11Event,GetMagickModule(),
04099 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
04100 event.xbutton.button,event.xbutton.x,event.xbutton.y);
04101 if (event.xbutton.button != Button1)
04102 break;
04103 if (event.xbutton.window != windows->image.id)
04104 break;
04105 if ((composite_info.width != 0) && (composite_info.height != 0))
04106 {
04107
04108
04109
04110 composite_info.x=windows->image.x+event.xbutton.x;
04111 composite_info.y=windows->image.y+event.xbutton.y;
04112 state|=ExitState;
04113 }
04114 break;
04115 }
04116 case Expose:
04117 break;
04118 case KeyPress:
04119 {
04120 char
04121 command[MaxTextExtent];
04122
04123 KeySym
04124 key_symbol;
04125
04126 int
04127 length;
04128
04129 if (event.xkey.window != windows->image.id)
04130 break;
04131
04132
04133
04134 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
04135 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
04136 *(command+length)='\0';
04137 if (image->debug != MagickFalse)
04138 (void) LogMagickEvent(X11Event,GetMagickModule(),
04139 "Key press: 0x%lx (%s)",(unsigned long) key_symbol,command);
04140 switch ((int) key_symbol)
04141 {
04142 case XK_Escape:
04143 case XK_F20:
04144 {
04145
04146
04147
04148 composite_image=DestroyImage(composite_image);
04149 state|=EscapeState;
04150 state|=ExitState;
04151 break;
04152 }
04153 case XK_F1:
04154 case XK_Help:
04155 {
04156 (void) XSetFunction(display,windows->image.highlight_context,
04157 GXcopy);
04158 XTextViewWidget(display,resource_info,windows,MagickFalse,
04159 "Help Viewer - Image Composite",ImageCompositeHelp);
04160 (void) XSetFunction(display,windows->image.highlight_context,
04161 GXinvert);
04162 break;
04163 }
04164 default:
04165 {
04166 (void) XBell(display,0);
04167 break;
04168 }
04169 }
04170 break;
04171 }
04172 case MotionNotify:
04173 {
04174
04175
04176
04177 x=event.xmotion.x;
04178 y=event.xmotion.y;
04179 if (windows->info.mapped != MagickFalse)
04180 {
04181 if ((x < (int) (windows->info.x+windows->info.width)) &&
04182 (y < (int) (windows->info.y+windows->info.height)))
04183 (void) XWithdrawWindow(display,windows->info.id,
04184 windows->info.screen);
04185 }
04186 else
04187 if ((x > (int) (windows->info.x+windows->info.width)) ||
04188 (y > (int) (windows->info.y+windows->info.height)))
04189 (void) XMapWindow(display,windows->info.id);
04190 composite_info.x=windows->image.x+x;
04191 composite_info.y=windows->image.y+y;
04192 break;
04193 }
04194 default:
04195 {
04196 if (image->debug != MagickFalse)
04197 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
04198 event.type);
04199 break;
04200 }
04201 }
04202 } while ((state & ExitState) == 0);
04203 (void) XSelectInput(display,windows->image.id,
04204 windows->image.attributes.event_mask);
04205 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
04206 XSetCursorState(display,windows,MagickFalse);
04207 (void) XFreeCursor(display,cursor);
04208 if ((state & EscapeState) != 0)
04209 return(MagickTrue);
04210
04211
04212
04213 XSetCursorState(display,windows,MagickTrue);
04214 XCheckRefreshWindows(display,windows);
04215 width=(unsigned int) image->columns;
04216 height=(unsigned int) image->rows;
04217 x=0;
04218 y=0;
04219 if (windows->image.crop_geometry != (char *) NULL)
04220 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
04221 scale_factor=(MagickRealType) width/windows->image.ximage->width;
04222 composite_info.x+=x;
04223 composite_info.x=(int) (scale_factor*composite_info.x+0.5);
04224 composite_info.width=(unsigned int) (scale_factor*composite_info.width+0.5);
04225 scale_factor=(MagickRealType) height/windows->image.ximage->height;
04226 composite_info.y+=y;
04227 composite_info.y=(int) (scale_factor*composite_info.y+0.5);
04228 composite_info.height=(unsigned int) (scale_factor*composite_info.height+0.5);
04229 if ((composite_info.width != composite_image->columns) ||
04230 (composite_info.height != composite_image->rows))
04231 {
04232 Image
04233 *resize_image;
04234
04235
04236
04237
04238 resize_image=ZoomImage(composite_image,composite_info.width,
04239 composite_info.height,&image->exception);
04240 composite_image=DestroyImage(composite_image);
04241 if (resize_image == (Image *) NULL)
04242 {
04243 XSetCursorState(display,windows,MagickFalse);
04244 return(MagickFalse);
04245 }
04246 composite_image=resize_image;
04247 }
04248 if (compose == DisplaceCompositeOp)
04249 (void) SetImageArtifact(composite_image,"compose:args",
04250 displacement_geometry);
04251 if (blend != 0.0)
04252 {
04253 ExceptionInfo
04254 *exception;
04255
04256 int
04257 y;
04258
04259 Quantum
04260 opacity;
04261
04262 register int
04263 x;
04264
04265 register PixelPacket
04266 *q;
04267
04268
04269
04270
04271 (void) SetImageAlphaChannel(composite_image,OpaqueAlphaChannel);
04272 opacity=(Quantum) (ScaleQuantumToChar((Quantum) QuantumRange)-
04273 ((long) ScaleQuantumToChar((Quantum) QuantumRange)*blend)/100);
04274 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
04275 return(MagickFalse);
04276 image->matte=MagickTrue;
04277 exception=(&image->exception);
04278 for (y=0; y < (long) image->rows; y++)
04279 {
04280 q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
04281 if (q == (PixelPacket *) NULL)
04282 break;
04283 for (x=0; x < (int) image->columns; x++)
04284 {
04285 q->opacity=opacity;
04286 q++;
04287 }
04288 if (SyncAuthenticPixels(image,exception) == MagickFalse)
04289 break;
04290 }
04291 }
04292
04293
04294
04295 (void) CompositeImage(image,compose,composite_image,composite_info.x,
04296 composite_info.y);
04297 composite_image=DestroyImage(composite_image);
04298 XSetCursorState(display,windows,MagickFalse);
04299
04300
04301
04302 XConfigureImageColormap(display,resource_info,windows,image);
04303 (void) XConfigureImage(display,resource_info,windows,image);
04304 return(MagickTrue);
04305 }
04306
04307
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 static MagickBooleanType XConfigureImage(Display *display,
04340 XResourceInfo *resource_info,XWindows *windows,Image *image)
04341 {
04342 char
04343 geometry[MaxTextExtent];
04344
04345 long
04346 x,
04347 y;
04348
04349 MagickStatusType
04350 status;
04351
04352 unsigned long
04353 mask,
04354 height,
04355 width;
04356
04357 XSizeHints
04358 *size_hints;
04359
04360 XWindowChanges
04361 window_changes;
04362
04363
04364
04365
04366 width=(unsigned int) windows->image.window_changes.width;
04367 height=(unsigned int) windows->image.window_changes.height;
04368 if (image->debug != MagickFalse)
04369 (void) LogMagickEvent(X11Event,GetMagickModule(),
04370 "Configure Image: %dx%d=>%lux%lu",windows->image.ximage->width,
04371 windows->image.ximage->height,width,height);
04372 if ((width*height) == 0)
04373 return(MagickTrue);
04374 x=0;
04375 y=0;
04376
04377
04378
04379 XSetCursorState(display,windows,MagickTrue);
04380 (void) XFlush(display);
04381 if (((int) width != windows->image.ximage->width) ||
04382 ((int) height != windows->image.ximage->height))
04383 image->taint=MagickTrue;
04384 windows->magnify.x=(int)
04385 width*windows->magnify.x/windows->image.ximage->width;
04386 windows->magnify.y=(int)
04387 height*windows->magnify.y/windows->image.ximage->height;
04388 windows->image.x=(int) (width*windows->image.x/windows->image.ximage->width);
04389 windows->image.y=(int)
04390 (height*windows->image.y/windows->image.ximage->height);
04391 status=XMakeImage(display,resource_info,&windows->image,image,
04392 (unsigned int) width,(unsigned int) height);
04393 if (status == MagickFalse)
04394 XNoticeWidget(display,windows,"Unable to configure X image:",
04395 windows->image.name);
04396
04397
04398
04399 if (resource_info->image_geometry != (char *) NULL)
04400 (void) FormatMagickString(geometry,MaxTextExtent,"%s>!",
04401 resource_info->image_geometry);
04402 else
04403 (void) FormatMagickString(geometry,MaxTextExtent,"%ux%u+0+0>!",
04404 XDisplayWidth(display,windows->image.screen),
04405 XDisplayHeight(display,windows->image.screen));
04406 (void) ParseMetaGeometry(geometry,&x,&y,&width,&height);
04407 window_changes.width=(int) width;
04408 if (window_changes.width > XDisplayWidth(display,windows->image.screen))
04409 window_changes.width=XDisplayWidth(display,windows->image.screen);
04410 window_changes.height=(int) height;
04411 if (window_changes.height > XDisplayHeight(display,windows->image.screen))
04412 window_changes.height=XDisplayHeight(display,windows->image.screen);
04413 mask=(unsigned long) (CWWidth | CWHeight);
04414 if (resource_info->backdrop)
04415 {
04416 mask|=CWX | CWY;
04417 window_changes.x=(int)
04418 ((XDisplayWidth(display,windows->image.screen)/2)-(width/2));
04419 window_changes.y=(int)
04420 ((XDisplayHeight(display,windows->image.screen)/2)-(height/2));
04421 }
04422 (void) XReconfigureWMWindow(display,windows->image.id,windows->image.screen,
04423 (unsigned int) mask,&window_changes);
04424 (void) XClearWindow(display,windows->image.id);
04425 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
04426
04427
04428
04429 if (windows->magnify.mapped != MagickFalse)
04430 XMakeMagnifyImage(display,windows);
04431 windows->pan.crop_geometry=windows->image.crop_geometry;
04432 XBestIconSize(display,&windows->pan,image);
04433 while (((windows->pan.width << 1) < MaxIconSize) &&
04434 ((windows->pan.height << 1) < MaxIconSize))
04435 {
04436 windows->pan.width<<=1;
04437 windows->pan.height<<=1;
04438 }
04439 if (windows->pan.geometry != (char *) NULL)
04440 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
04441 &windows->pan.width,&windows->pan.height);
04442 window_changes.width=(int) windows->pan.width;
04443 window_changes.height=(int) windows->pan.height;
04444 size_hints=XAllocSizeHints();
04445 if (size_hints != (XSizeHints *) NULL)
04446 {
04447