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/string-private.h"
00084 #include "magick/transform.h"
00085 #include "magick/threshold.h"
00086 #include "magick/utility.h"
00087 #include "magick/version.h"
00088 #include "magick/widget.h"
00089 #include "magick/xwindow-private.h"
00090
00091 #if defined(MAGICKCORE_X11_DELEGATE)
00092
00093
00094
00095 #define MaxColors MagickMin(windows->visual_info->colormap_size,256L)
00096
00097
00098
00099
00100 static const unsigned char
00101 HighlightBitmap[8] =
00102 {
00103 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55
00104 },
00105 ShadowBitmap[8] =
00106 {
00107 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
00108 };
00109
00110 static const char
00111 *PageSizes[] =
00112 {
00113 "Letter",
00114 "Tabloid",
00115 "Ledger",
00116 "Legal",
00117 "Statement",
00118 "Executive",
00119 "A3",
00120 "A4",
00121 "A5",
00122 "B4",
00123 "B5",
00124 "Folio",
00125 "Quarto",
00126 "10x14",
00127 (char *) NULL
00128 };
00129
00130
00131
00132
00133 static const char
00134 *ImageAnnotateHelp[] =
00135 {
00136 "In annotate mode, the Command widget has these options:",
00137 "",
00138 " Font Name",
00139 " fixed",
00140 " variable",
00141 " 5x8",
00142 " 6x10",
00143 " 7x13bold",
00144 " 8x13bold",
00145 " 9x15bold",
00146 " 10x20",
00147 " 12x24",
00148 " Browser...",
00149 " Font Color",
00150 " black",
00151 " blue",
00152 " cyan",
00153 " green",
00154 " gray",
00155 " red",
00156 " magenta",
00157 " yellow",
00158 " white",
00159 " transparent",
00160 " Browser...",
00161 " Font Color",
00162 " black",
00163 " blue",
00164 " cyan",
00165 " green",
00166 " gray",
00167 " red",
00168 " magenta",
00169 " yellow",
00170 " white",
00171 " transparent",
00172 " Browser...",
00173 " Rotate Text",
00174 " -90",
00175 " -45",
00176 " -30",
00177 " 0",
00178 " 30",
00179 " 45",
00180 " 90",
00181 " 180",
00182 " Dialog...",
00183 " Help",
00184 " Dismiss",
00185 "",
00186 "Choose a font name from the Font Name sub-menu. Additional",
00187 "font names can be specified with the font browser. You can",
00188 "change the menu names by setting the X resources font1",
00189 "through font9.",
00190 "",
00191 "Choose a font color from the Font Color sub-menu.",
00192 "Additional font colors can be specified with the color",
00193 "browser. You can change the menu colors by setting the X",
00194 "resources pen1 through pen9.",
00195 "",
00196 "If you select the color browser and press Grab, you can",
00197 "choose the font color by moving the pointer to the desired",
00198 "color on the screen and press any button.",
00199 "",
00200 "If you choose to rotate the text, choose Rotate Text from the",
00201 "menu and select an angle. Typically you will only want to",
00202 "rotate one line of text at a time. Depending on the angle you",
00203 "choose, subsequent lines may end up overwriting each other.",
00204 "",
00205 "Choosing a font and its color is optional. The default font",
00206 "is fixed and the default color is black. However, you must",
00207 "choose a location to begin entering text and press button 1.",
00208 "An underscore character will appear at the location of the",
00209 "pointer. The cursor changes to a pencil to indicate you are",
00210 "in text mode. To exit immediately, press Dismiss.",
00211 "",
00212 "In text mode, any key presses will display the character at",
00213 "the location of the underscore and advance the underscore",
00214 "cursor. Enter your text and once completed press Apply to",
00215 "finish your image annotation. To correct errors press BACK",
00216 "SPACE. To delete an entire line of text, press DELETE. Any",
00217 "text that exceeds the boundaries of the image window is",
00218 "automagically continued onto the next line.",
00219 "",
00220 "The actual color you request for the font is saved in the",
00221 "image. However, the color that appears in your image window",
00222 "may be different. For example, on a monochrome screen the",
00223 "text will appear black or white even if you choose the color",
00224 "red as the font color. However, the image saved to a file",
00225 "with -write is written with red lettering. To assure the",
00226 "correct color text in the final image, any PseudoClass image",
00227 "is promoted to DirectClass (see miff(5)). To force a",
00228 "PseudoClass image to remain PseudoClass, use -colors.",
00229 (char *) NULL,
00230 },
00231 *ImageChopHelp[] =
00232 {
00233 "In chop mode, the Command widget has these options:",
00234 "",
00235 " Direction",
00236 " horizontal",
00237 " vertical",
00238 " Help",
00239 " Dismiss",
00240 "",
00241 "If the you choose the horizontal direction (this the",
00242 "default), the area of the image between the two horizontal",
00243 "endpoints of the chop line is removed. Otherwise, the area",
00244 "of the image between the two vertical endpoints of the chop",
00245 "line is removed.",
00246 "",
00247 "Select a location within the image window to begin your chop,",
00248 "press and hold any button. Next, move the pointer to",
00249 "another location in the image. As you move a line will",
00250 "connect the initial location and the pointer. When you",
00251 "release the button, the area within the image to chop is",
00252 "determined by which direction you choose from the Command",
00253 "widget.",
00254 "",
00255 "To cancel the image chopping, move the pointer back to the",
00256 "starting point of the line and release the button.",
00257 (char *) NULL,
00258 },
00259 *ImageColorEditHelp[] =
00260 {
00261 "In color edit mode, the Command widget has these options:",
00262 "",
00263 " Method",
00264 " point",
00265 " replace",
00266 " floodfill",
00267 " filltoborder",
00268 " reset",
00269 " Pixel Color",
00270 " black",
00271 " blue",
00272 " cyan",
00273 " green",
00274 " gray",
00275 " red",
00276 " magenta",
00277 " yellow",
00278 " white",
00279 " Browser...",
00280 " Border Color",
00281 " black",
00282 " blue",
00283 " cyan",
00284 " green",
00285 " gray",
00286 " red",
00287 " magenta",
00288 " yellow",
00289 " white",
00290 " Browser...",
00291 " Fuzz",
00292 " 0%",
00293 " 2%",
00294 " 5%",
00295 " 10%",
00296 " 15%",
00297 " Dialog...",
00298 " Undo",
00299 " Help",
00300 " Dismiss",
00301 "",
00302 "Choose a color editing method from the Method sub-menu",
00303 "of the Command widget. The point method recolors any pixel",
00304 "selected with the pointer until the button is released. The",
00305 "replace method recolors any pixel that matches the color of",
00306 "the pixel you select with a button press. Floodfill recolors",
00307 "any pixel that matches the color of the pixel you select with",
00308 "a button press and is a neighbor. Whereas filltoborder recolors",
00309 "any neighbor pixel that is not the border color. Finally reset",
00310 "changes the entire image to the designated color.",
00311 "",
00312 "Next, choose a pixel color from the Pixel Color sub-menu.",
00313 "Additional pixel colors can be specified with the color",
00314 "browser. You can change the menu colors by setting the X",
00315 "resources pen1 through pen9.",
00316 "",
00317 "Now press button 1 to select a pixel within the image window",
00318 "to change its color. Additional pixels may be recolored as",
00319 "prescribed by the method you choose.",
00320 "",
00321 "If the Magnify widget is mapped, it can be helpful in positioning",
00322 "your pointer within the image (refer to button 2).",
00323 "",
00324 "The actual color you request for the pixels is saved in the",
00325 "image. However, the color that appears in your image window",
00326 "may be different. For example, on a monochrome screen the",
00327 "pixel will appear black or white even if you choose the",
00328 "color red as the pixel color. However, the image saved to a",
00329 "file with -write is written with red pixels. To assure the",
00330 "correct color text in the final image, any PseudoClass image",
00331 "is promoted to DirectClass (see miff(5)). To force a",
00332 "PseudoClass image to remain PseudoClass, use -colors.",
00333 (char *) NULL,
00334 },
00335 *ImageCompositeHelp[] =
00336 {
00337 "First a widget window is displayed requesting you to enter an",
00338 "image name. Press Composite, Grab or type a file name.",
00339 "Press Cancel if you choose not to create a composite image.",
00340 "When you choose Grab, move the pointer to the desired window",
00341 "and press any button.",
00342 "",
00343 "If the Composite image does not have any matte information,",
00344 "you are informed and the file browser is displayed again.",
00345 "Enter the name of a mask image. The image is typically",
00346 "grayscale and the same size as the composite image. If the",
00347 "image is not grayscale, it is converted to grayscale and the",
00348 "resulting intensities are used as matte information.",
00349 "",
00350 "A small window appears showing the location of the cursor in",
00351 "the image window. You are now in composite mode. To exit",
00352 "immediately, press Dismiss. In composite mode, the Command",
00353 "widget has these options:",
00354 "",
00355 " Operators",
00356 " Over",
00357 " In",
00358 " Out",
00359 " Atop",
00360 " Xor",
00361 " Plus",
00362 " Minus",
00363 " Add",
00364 " Subtract",
00365 " Difference",
00366 " Multiply",
00367 " Bumpmap",
00368 " Copy",
00369 " CopyRed",
00370 " CopyGreen",
00371 " CopyBlue",
00372 " CopyOpacity",
00373 " Clear",
00374 " Dissolve",
00375 " Displace",
00376 " Help",
00377 " Dismiss",
00378 "",
00379 "Choose a composite operation from the Operators sub-menu of",
00380 "the Command widget. How each operator behaves is described",
00381 "below. Image window is the image currently displayed on",
00382 "your X server and image is the image obtained with the File",
00383 "Browser widget.",
00384 "",
00385 "Over The result is the union of the two image shapes,",
00386 " with image obscuring image window in the region of",
00387 " overlap.",
00388 "",
00389 "In The result is simply image cut by the shape of",
00390 " image window. None of the image data of image",
00391 " window is in the result.",
00392 "",
00393 "Out The resulting image is image with the shape of",
00394 " image window cut out.",
00395 "",
00396 "Atop The result is the same shape as image image window,",
00397 " with image obscuring image window where the image",
00398 " shapes overlap. Note this differs from over",
00399 " because the portion of image outside image window's",
00400 " shape does not appear in the result.",
00401 "",
00402 "Xor The result is the image data from both image and",
00403 " image window that is outside the overlap region.",
00404 " The overlap region is blank.",
00405 "",
00406 "Plus The result is just the sum of the image data.",
00407 " Output values are cropped to QuantumRange (no overflow).",
00408 "",
00409 "Minus The result of image - image window, with underflow",
00410 " cropped to zero.",
00411 "",
00412 "Add The result of image + image window, with overflow",
00413 " wrapping around (mod 256).",
00414 "",
00415 "Subtract The result of image - image window, with underflow",
00416 " wrapping around (mod 256). The add and subtract",
00417 " operators can be used to perform reversible",
00418 " transformations.",
00419 "",
00420 "Difference",
00421 " The result of abs(image - image window). This",
00422 " useful for comparing two very similar images.",
00423 "",
00424 "Multiply",
00425 " The result of image * image window. This",
00426 " useful for the creation of drop-shadows.",
00427 "",
00428 "Bumpmap The result of surface normals from image * image",
00429 " window.",
00430 "",
00431 "Copy The resulting image is image window replaced with",
00432 " image. Here the matte information is ignored.",
00433 "",
00434 "CopyRed The red layer of the image window is replace with",
00435 " the red layer of the image. The other layers are",
00436 " untouched.",
00437 "",
00438 "CopyGreen",
00439 " The green layer of the image window is replace with",
00440 " the green layer of the image. The other layers are",
00441 " untouched.",
00442 "",
00443 "CopyBlue The blue layer of the image window is replace with",
00444 " the blue layer of the image. The other layers are",
00445 " untouched.",
00446 "",
00447 "CopyOpacity",
00448 " The matte layer of the image window is replace with",
00449 " the matte layer of the image. The other layers are",
00450 " untouched.",
00451 "",
00452 "The image compositor requires a matte, or alpha channel in",
00453 "the image for some operations. This extra channel usually",
00454 "defines a mask which represents a sort of a cookie-cutter",
00455 "for the image. This the case when matte is opaque (full",
00456 "coverage) for pixels inside the shape, zero outside, and",
00457 "between 0 and QuantumRange on the boundary. If image does not",
00458 "have a matte channel, it is initialized with 0 for any pixel",
00459 "matching in color to pixel location (0,0), otherwise QuantumRange.",
00460 "",
00461 "If you choose Dissolve, the composite operator becomes Over. The",
00462 "image matte channel percent transparency is initialized to factor.",
00463 "The image window is initialized to (100-factor). Where factor is the",
00464 "value you specify in the Dialog widget.",
00465 "",
00466 "Displace shifts the image pixels as defined by a displacement",
00467 "map. With this option, image is used as a displacement map.",
00468 "Black, within the displacement map, is a maximum positive",
00469 "displacement. White is a maximum negative displacement and",
00470 "middle gray is neutral. The displacement is scaled to determine",
00471 "the pixel shift. By default, the displacement applies in both the",
00472 "horizontal and vertical directions. However, if you specify a mask,",
00473 "image is the horizontal X displacement and mask the vertical Y",
00474 "displacement.",
00475 "",
00476 "Note that matte information for image window is not retained",
00477 "for colormapped X server visuals (e.g. StaticColor,",
00478 "StaticColor, GrayScale, PseudoColor). Correct compositing",
00479 "behavior may require a TrueColor or DirectColor visual or a",
00480 "Standard Colormap.",
00481 "",
00482 "Choosing a composite operator is optional. The default",
00483 "operator is replace. However, you must choose a location to",
00484 "composite your image and press button 1. Press and hold the",
00485 "button before releasing and an outline of the image will",
00486 "appear to help you identify your location.",
00487 "",
00488 "The actual colors of the composite image is saved. However,",
00489 "the color that appears in image window may be different.",
00490 "For example, on a monochrome screen image window will appear",
00491 "black or white even though your composited image may have",
00492 "many colors. If the image is saved to a file it is written",
00493 "with the correct colors. To assure the correct colors are",
00494 "saved in the final image, any PseudoClass image is promoted",
00495 "to DirectClass (see miff(5)). To force a PseudoClass image",
00496 "to remain PseudoClass, use -colors.",
00497 (char *) NULL,
00498 },
00499 *ImageCutHelp[] =
00500 {
00501 "In cut mode, the Command widget has these options:",
00502 "",
00503 " Help",
00504 " Dismiss",
00505 "",
00506 "To define a cut region, press button 1 and drag. The",
00507 "cut region is defined by a highlighted rectangle that",
00508 "expands or contracts as it follows the pointer. Once you",
00509 "are satisfied with the cut region, release the button.",
00510 "You are now in rectify mode. In rectify mode, the Command",
00511 "widget has these options:",
00512 "",
00513 " Cut",
00514 " Help",
00515 " Dismiss",
00516 "",
00517 "You can make adjustments by moving the pointer to one of the",
00518 "cut rectangle corners, pressing a button, and dragging.",
00519 "Finally, press Cut to commit your copy region. To",
00520 "exit without cutting the image, press Dismiss.",
00521 (char *) NULL,
00522 },
00523 *ImageCopyHelp[] =
00524 {
00525 "In copy mode, the Command widget has these options:",
00526 "",
00527 " Help",
00528 " Dismiss",
00529 "",
00530 "To define a copy region, press button 1 and drag. The",
00531 "copy region is defined by a highlighted rectangle that",
00532 "expands or contracts as it follows the pointer. Once you",
00533 "are satisfied with the copy region, release the button.",
00534 "You are now in rectify mode. In rectify mode, the Command",
00535 "widget has these options:",
00536 "",
00537 " Copy",
00538 " Help",
00539 " Dismiss",
00540 "",
00541 "You can make adjustments by moving the pointer to one of the",
00542 "copy rectangle corners, pressing a button, and dragging.",
00543 "Finally, press Copy to commit your copy region. To",
00544 "exit without copying the image, press Dismiss.",
00545 (char *) NULL,
00546 },
00547 *ImageCropHelp[] =
00548 {
00549 "In crop mode, the Command widget has these options:",
00550 "",
00551 " Help",
00552 " Dismiss",
00553 "",
00554 "To define a cropping region, press button 1 and drag. The",
00555 "cropping region is defined by a highlighted rectangle that",
00556 "expands or contracts as it follows the pointer. Once you",
00557 "are satisfied with the cropping region, release the button.",
00558 "You are now in rectify mode. In rectify mode, the Command",
00559 "widget has these options:",
00560 "",
00561 " Crop",
00562 " Help",
00563 " Dismiss",
00564 "",
00565 "You can make adjustments by moving the pointer to one of the",
00566 "cropping rectangle corners, pressing a button, and dragging.",
00567 "Finally, press Crop to commit your cropping region. To",
00568 "exit without cropping the image, press Dismiss.",
00569 (char *) NULL,
00570 },
00571 *ImageDrawHelp[] =
00572 {
00573 "The cursor changes to a crosshair to indicate you are in",
00574 "draw mode. To exit immediately, press Dismiss. In draw mode,",
00575 "the Command widget has these options:",
00576 "",
00577 " Element",
00578 " point",
00579 " line",
00580 " rectangle",
00581 " fill rectangle",
00582 " circle",
00583 " fill circle",
00584 " ellipse",
00585 " fill ellipse",
00586 " polygon",
00587 " fill polygon",
00588 " Color",
00589 " black",
00590 " blue",
00591 " cyan",
00592 " green",
00593 " gray",
00594 " red",
00595 " magenta",
00596 " yellow",
00597 " white",
00598 " transparent",
00599 " Browser...",
00600 " Stipple",
00601 " Brick",
00602 " Diagonal",
00603 " Scales",
00604 " Vertical",
00605 " Wavy",
00606 " Translucent",
00607 " Opaque",
00608 " Open...",
00609 " Width",
00610 " 1",
00611 " 2",
00612 " 4",
00613 " 8",
00614 " 16",
00615 " Dialog...",
00616 " Undo",
00617 " Help",
00618 " Dismiss",
00619 "",
00620 "Choose a drawing primitive from the Element sub-menu.",
00621 "",
00622 "Choose a color from the Color sub-menu. Additional",
00623 "colors can be specified with the color browser.",
00624 "",
00625 "If you choose the color browser and press Grab, you can",
00626 "select the color by moving the pointer to the desired",
00627 "color on the screen and press any button. The transparent",
00628 "color updates the image matte channel and is useful for",
00629 "image compositing.",
00630 "",
00631 "Choose a stipple, if appropriate, from the Stipple sub-menu.",
00632 "Additional stipples can be specified with the file browser.",
00633 "Stipples obtained from the file browser must be on disk in the",
00634 "X11 bitmap format.",
00635 "",
00636 "Choose a width, if appropriate, from the Width sub-menu. To",
00637 "choose a specific width select the Dialog widget.",
00638 "",
00639 "Choose a point in the Image window and press button 1 and",
00640 "hold. Next, move the pointer to another location in the",
00641 "image. As you move, a line connects the initial location and",
00642 "the pointer. When you release the button, the image is",
00643 "updated with the primitive you just drew. For polygons, the",
00644 "image is updated when you press and release the button without",
00645 "moving the pointer.",
00646 "",
00647 "To cancel image drawing, move the pointer back to the",
00648 "starting point of the line and release the button.",
00649 (char *) NULL,
00650 },
00651 *DisplayHelp[] =
00652 {
00653 "BUTTONS",
00654 " The effects of each button press is described below. Three",
00655 " buttons are required. If you have a two button mouse,",
00656 " button 1 and 3 are returned. Press ALT and button 3 to",
00657 " simulate button 2.",
00658 "",
00659 " 1 Press this button to map or unmap the Command widget.",
00660 "",
00661 " 2 Press and drag to define a region of the image to",
00662 " magnify.",
00663 "",
00664 " 3 Press and drag to choose from a select set of commands.",
00665 " This button behaves differently if the image being",
00666 " displayed is a visual image directory. Here, choose a",
00667 " particular tile of the directory and press this button and",
00668 " drag to select a command from a pop-up menu. Choose from",
00669 " these menu items:",
00670 "",
00671 " Open",
00672 " Next",
00673 " Former",
00674 " Delete",
00675 " Update",
00676 "",
00677 " If you choose Open, the image represented by the tile is",
00678 " displayed. To return to the visual image directory, choose",
00679 " Next from the Command widget. Next and Former moves to the",
00680 " next or former image respectively. Choose Delete to delete",
00681 " a particular image tile. Finally, choose Update to",
00682 " synchronize all the image tiles with their respective",
00683 " images.",
00684 "",
00685 "COMMAND WIDGET",
00686 " The Command widget lists a number of sub-menus and commands.",
00687 " They are",
00688 "",
00689 " File",
00690 " Open...",
00691 " Next",
00692 " Former",
00693 " Select...",
00694 " Save...",
00695 " Print...",
00696 " Delete...",
00697 " New...",
00698 " Visual Directory...",
00699 " Quit",
00700 " Edit",
00701 " Undo",
00702 " Redo",
00703 " Cut",
00704 " Copy",
00705 " Paste",
00706 " View",
00707 " Half Size",
00708 " Original Size",
00709 " Double Size",
00710 " Resize...",
00711 " Apply",
00712 " Refresh",
00713 " Restore",
00714 " Transform",
00715 " Crop",
00716 " Chop",
00717 " Flop",
00718 " Flip",
00719 " Rotate Right",
00720 " Rotate Left",
00721 " Rotate...",
00722 " Shear...",
00723 " Roll...",
00724 " Trim Edges",
00725 " Enhance",
00726 " Brightness...",
00727 " Saturation...",
00728 " Hue...",
00729 " Gamma...",
00730 " Sharpen...",
00731 " Dull",
00732 " Contrast Stretch...",
00733 " Sigmoidal Contrast...",
00734 " Normalize",
00735 " Equalize",
00736 " Negate",
00737 " Grayscale",
00738 " Map...",
00739 " Quantize...",
00740 " Effects",
00741 " Despeckle",
00742 " Emboss",
00743 " Reduce Noise",
00744 " Add Noise",
00745 " Sharpen...",
00746 " Blur...",
00747 " Threshold...",
00748 " Edge Detect...",
00749 " Spread...",
00750 " Shade...",
00751 " Painting...",
00752 " Segment...",
00753 " F/X",
00754 " Solarize...",
00755 " Sepia Tone...",
00756 " Swirl...",
00757 " Implode...",
00758 " Vignette...",
00759 " Wave...",
00760 " Oil Painting...",
00761 " Charcoal Drawing...",
00762 " Image Edit",
00763 " Annotate...",
00764 " Draw...",
00765 " Color...",
00766 " Matte...",
00767 " Composite...",
00768 " Add Border...",
00769 " Add Frame...",
00770 " Comment...",
00771 " Launch...",
00772 " Region of Interest...",
00773 " Miscellany",
00774 " Image Info",
00775 " Zoom Image",
00776 " Show Preview...",
00777 " Show Histogram",
00778 " Show Matte",
00779 " Background...",
00780 " Slide Show",
00781 " Preferences...",
00782 " Help",
00783 " Overview",
00784 " Browse Documentation",
00785 " About Display",
00786 "",
00787 " Menu items with a indented triangle have a sub-menu. They",
00788 " are represented above as the indented items. To access a",
00789 " sub-menu item, move the pointer to the appropriate menu and",
00790 " press a button and drag. When you find the desired sub-menu",
00791 " item, release the button and the command is executed. Move",
00792 " the pointer away from the sub-menu if you decide not to",
00793 " execute a particular command.",
00794 "",
00795 "KEYBOARD ACCELERATORS",
00796 " Accelerators are one or two key presses that effect a",
00797 " particular command. The keyboard accelerators that",
00798 " display(1) understands is:",
00799 "",
00800 " Ctl+O Press to open an image from a file.",
00801 "",
00802 " space Press to display the next image.",
00803 "",
00804 " If the image is a multi-paged document such as a Postscript",
00805 " document, you can skip ahead several pages by preceding",
00806 " this command with a number. For example to display the",
00807 " third page beyond the current page, press 3<space>.",
00808 "",
00809 " backspace Press to display the former image.",
00810 "",
00811 " If the image is a multi-paged document such as a Postscript",
00812 " document, you can skip behind several pages by preceding",
00813 " this command with a number. For example to display the",
00814 " third page preceding the current page, press 3<backspace>.",
00815 "",
00816 " Ctl+S Press to write the image to a file.",
00817 "",
00818 " Ctl+P Press to print the image to a Postscript printer.",
00819 "",
00820 " Ctl+D Press to delete an image file.",
00821 "",
00822 " Ctl+N Press to create a blank canvas.",
00823 "",
00824 " Ctl+Q Press to discard all images and exit program.",
00825 "",
00826 " Ctl+Z Press to undo last image transformation.",
00827 "",
00828 " Ctl+R Press to redo last image transformation.",
00829 "",
00830 " Ctl+X Press to cut a region of the image.",
00831 "",
00832 " Ctl+C Press to copy a region of the image.",
00833 "",
00834 " Ctl+V Press to paste a region to the image.",
00835 "",
00836 " < Press to half the image size.",
00837 "",
00838 " - Press to return to the original image size.",
00839 "",
00840 " > Press to double the image size.",
00841 "",
00842 " % Press to resize the image to a width and height you",
00843 " specify.",
00844 "",
00845 "Cmd-A Press to make any image transformations permanent."
00846 "",
00847 " By default, any image size transformations are applied",
00848 " to the original image to create the image displayed on",
00849 " the X server. However, the transformations are not",
00850 " permanent (i.e. the original image does not change",
00851 " size only the X image does). For example, if you",
00852 " press > the X image will appear to double in size,",
00853 " but the original image will in fact remain the same size.",
00854 " To force the original image to double in size, press >",
00855 " followed by Cmd-A.",
00856 "",
00857 " @ Press to refresh the image window.",
00858 "",
00859 " C Press to cut out a rectangular region of the image.",
00860 "",
00861 " [ Press to chop the image.",
00862 "",
00863 " H Press to flop image in the horizontal direction.",
00864 "",
00865 " V Press to flip image in the vertical direction.",
00866 "",
00867 " / Press to rotate the image 90 degrees clockwise.",
00868 "",
00869 " \\ Press to rotate the image 90 degrees counter-clockwise.",
00870 "",
00871 " * Press to rotate the image the number of degrees you",
00872 " specify.",
00873 "",
00874 " S Press to shear the image the number of degrees you",
00875 " specify.",
00876 "",
00877 " R Press to roll the image.",
00878 "",
00879 " T Press to trim the image edges.",
00880 "",
00881 " Shft-H Press to vary the image hue.",
00882 "",
00883 " Shft-S Press to vary the color saturation.",
00884 "",
00885 " Shft-L Press to vary the color brightness.",
00886 "",
00887 " Shft-G Press to gamma correct the image.",
00888 "",
00889 " Shft-C Press to sharpen the image contrast.",
00890 "",
00891 " Shft-Z Press to dull the image contrast.",
00892 "",
00893 " = Press to perform histogram equalization on the image.",
00894 "",
00895 " Shft-N Press to perform histogram normalization on the image.",
00896 "",
00897 " Shft-~ Press to negate the colors of the image.",
00898 "",
00899 " . Press to convert the image colors to gray.",
00900 "",
00901 " Shft-# Press to set the maximum number of unique colors in the",
00902 " image.",
00903 "",
00904 " F2 Press to reduce the speckles in an image.",
00905 "",
00906 " F3 Press to eliminate peak noise from an image.",
00907 "",
00908 " F4 Press to add noise to an image.",
00909 "",
00910 " F5 Press to sharpen an image.",
00911 "",
00912 " F6 Press to delete an image file.",
00913 "",
00914 " F7 Press to threshold the image.",
00915 "",
00916 " F8 Press to detect edges within an image.",
00917 "",
00918 " F9 Press to emboss an image.",
00919 "",
00920 " F10 Press to displace pixels by a random amount.",
00921 "",
00922 " F11 Press to negate all pixels above the threshold level.",
00923 "",
00924 " F12 Press to shade the image using a distant light source.",
00925 "",
00926 " F13 Press to lighten or darken image edges to create a 3-D effect.",
00927 "",
00928 " F14 Press to segment the image by color.",
00929 "",
00930 " Meta-S Press to swirl image pixels about the center.",
00931 "",
00932 " Meta-I Press to implode image pixels about the center.",
00933 "",
00934 " Meta-W Press to alter an image along a sine wave.",
00935 "",
00936 " Meta-P Press to simulate an oil painting.",
00937 "",
00938 " Meta-C Press to simulate a charcoal drawing.",
00939 "",
00940 " Alt-A Press to annotate the image with text.",
00941 "",
00942 " Alt-D Press to draw on an image.",
00943 "",
00944 " Alt-P Press to edit an image pixel color.",
00945 "",
00946 " Alt-M Press to edit the image matte information.",
00947 "",
00948 " Alt-V Press to composite the image with another.",
00949 "",
00950 " Alt-B Press to add a border to the image.",
00951 "",
00952 " Alt-F Press to add an ornamental border to the image.",
00953 "",
00954 " Alt-Shft-!",
00955 " Press to add an image comment.",
00956 "",
00957 " Ctl-A Press to apply image processing techniques to a region",
00958 " of interest.",
00959 "",
00960 " Shft-? Press to display information about the image.",
00961 "",
00962 " Shft-+ Press to map the zoom image window.",
00963 "",
00964 " Shft-P Press to preview an image enhancement, effect, or f/x.",
00965 "",
00966 " F1 Press to display helpful information about display(1).",
00967 "",
00968 " Find Press to browse documentation about ImageMagick.",
00969 "",
00970 " 1-9 Press to change the level of magnification.",
00971 "",
00972 " Use the arrow keys to move the image one pixel up, down,",
00973 " left, or right within the magnify window. Be sure to first",
00974 " map the magnify window by pressing button 2.",
00975 "",
00976 " Press ALT and one of the arrow keys to trim off one pixel",
00977 " from any side of the image.",
00978 (char *) NULL,
00979 },
00980 *ImageMatteEditHelp[] =
00981 {
00982 "Matte information within an image is useful for some",
00983 "operations such as image compositing (See IMAGE",
00984 "COMPOSITING). This extra channel usually defines a mask",
00985 "which represents a sort of a cookie-cutter for the image.",
00986 "This the case when matte is opaque (full coverage) for",
00987 "pixels inside the shape, zero outside, and between 0 and",
00988 "QuantumRange on the boundary.",
00989 "",
00990 "A small window appears showing the location of the cursor in",
00991 "the image window. You are now in matte edit mode. To exit",
00992 "immediately, press Dismiss. In matte edit mode, the Command",
00993 "widget has these options:",
00994 "",
00995 " Method",
00996 " point",
00997 " replace",
00998 " floodfill",
00999 " filltoborder",
01000 " reset",
01001 " Border Color",
01002 " black",
01003 " blue",
01004 " cyan",
01005 " green",
01006 " gray",
01007 " red",
01008 " magenta",
01009 " yellow",
01010 " white",
01011 " Browser...",
01012 " Fuzz",
01013 " 0%",
01014 " 2%",
01015 " 5%",
01016 " 10%",
01017 " 15%",
01018 " Dialog...",
01019 " Matte",
01020 " Opaque",
01021 " Transparent",
01022 " Dialog...",
01023 " Undo",
01024 " Help",
01025 " Dismiss",
01026 "",
01027 "Choose a matte editing method from the Method sub-menu of",
01028 "the Command widget. The point method changes the matte value",
01029 "of any pixel selected with the pointer until the button is",
01030 "is released. The replace method changes the matte value of",
01031 "any pixel that matches the color of the pixel you select with",
01032 "a button press. Floodfill changes the matte value of any pixel",
01033 "that matches the color of the pixel you select with a button",
01034 "press and is a neighbor. Whereas filltoborder changes the matte",
01035 "value any neighbor pixel that is not the border color. Finally",
01036 "reset changes the entire image to the designated matte value.",
01037 "",
01038 "Choose Matte Value and pick Opaque or Transarent. For other values",
01039 "select the Dialog entry. Here a dialog appears requesting a matte",
01040 "value. The value you select is assigned as the opacity value of the",
01041 "selected pixel or pixels.",
01042 "",
01043 "Now, press any button to select a pixel within the image",
01044 "window to change its matte value.",
01045 "",
01046 "If the Magnify widget is mapped, it can be helpful in positioning",
01047 "your pointer within the image (refer to button 2).",
01048 "",
01049 "Matte information is only valid in a DirectClass image.",
01050 "Therefore, any PseudoClass image is promoted to DirectClass",
01051 "(see miff(5)). Note that matte information for PseudoClass",
01052 "is not retained for colormapped X server visuals (e.g.",
01053 "StaticColor, StaticColor, GrayScale, PseudoColor) unless you",
01054 "immediately save your image to a file (refer to Write).",
01055 "Correct matte editing behavior may require a TrueColor or",
01056 "DirectColor visual or a Standard Colormap.",
01057 (char *) NULL,
01058 },
01059 *ImagePanHelp[] =
01060 {
01061 "When an image exceeds the width or height of the X server",
01062 "screen, display maps a small panning icon. The rectangle",
01063 "within the panning icon shows the area that is currently",
01064 "displayed in the image window. To pan about the image,",
01065 "press any button and drag the pointer within the panning",
01066 "icon. The pan rectangle moves with the pointer and the",
01067 "image window is updated to reflect the location of the",
01068 "rectangle within the panning icon. When you have selected",
01069 "the area of the image you wish to view, release the button.",
01070 "",
01071 "Use the arrow keys to pan the image one pixel up, down,",
01072 "left, or right within the image window.",
01073 "",
01074 "The panning icon is withdrawn if the image becomes smaller",
01075 "than the dimensions of the X server screen.",
01076 (char *) NULL,
01077 },
01078 *ImagePasteHelp[] =
01079 {
01080 "A small window appears showing the location of the cursor in",
01081 "the image window. You are now in paste mode. To exit",
01082 "immediately, press Dismiss. In paste mode, the Command",
01083 "widget has these options:",
01084 "",
01085 " Operators",
01086 " over",
01087 " in",
01088 " out",
01089 " atop",
01090 " xor",
01091 " plus",
01092 " minus",
01093 " add",
01094 " subtract",
01095 " difference",
01096 " replace",
01097 " Help",
01098 " Dismiss",
01099 "",
01100 "Choose a composite operation from the Operators sub-menu of",
01101 "the Command widget. How each operator behaves is described",
01102 "below. Image window is the image currently displayed on",
01103 "your X server and image is the image obtained with the File",
01104 "Browser widget.",
01105 "",
01106 "Over The result is the union of the two image shapes,",
01107 " with image obscuring image window in the region of",
01108 " overlap.",
01109 "",
01110 "In The result is simply image cut by the shape of",
01111 " image window. None of the image data of image",
01112 " window is in the result.",
01113 "",
01114 "Out The resulting image is image with the shape of",
01115 " image window cut out.",
01116 "",
01117 "Atop The result is the same shape as image image window,",
01118 " with image obscuring image window where the image",
01119 " shapes overlap. Note this differs from over",
01120 " because the portion of image outside image window's",
01121 " shape does not appear in the result.",
01122 "",
01123 "Xor The result is the image data from both image and",
01124 " image window that is outside the overlap region.",
01125 " The overlap region is blank.",
01126 "",
01127 "Plus The result is just the sum of the image data.",
01128 " Output values are cropped to QuantumRange (no overflow).",
01129 " This operation is independent of the matte",
01130 " channels.",
01131 "",
01132 "Minus The result of image - image window, with underflow",
01133 " cropped to zero.",
01134 "",
01135 "Add The result of image + image window, with overflow",
01136 " wrapping around (mod 256).",
01137 "",
01138 "Subtract The result of image - image window, with underflow",
01139 " wrapping around (mod 256). The add and subtract",
01140 " operators can be used to perform reversible",
01141 " transformations.",
01142 "",
01143 "Difference",
01144 " The result of abs(image - image window). This",
01145 " useful for comparing two very similar images.",
01146 "",
01147 "Copy The resulting image is image window replaced with",
01148 " image. Here the matte information is ignored.",
01149 "",
01150 "CopyRed The red layer of the image window is replace with",
01151 " the red layer of the image. The other layers are",
01152 " untouched.",
01153 "",
01154 "CopyGreen",
01155 " The green layer of the image window is replace with",
01156 " the green layer of the image. The other layers are",
01157 " untouched.",
01158 "",
01159 "CopyBlue The blue layer of the image window is replace with",
01160 " the blue layer of the image. The other layers are",
01161 " untouched.",
01162 "",
01163 "CopyOpacity",
01164 " The matte layer of the image window is replace with",
01165 " the matte layer of the image. The other layers are",
01166 " untouched.",
01167 "",
01168 "The image compositor requires a matte, or alpha channel in",
01169 "the image for some operations. This extra channel usually",
01170 "defines a mask which represents a sort of a cookie-cutter",
01171 "for the image. This the case when matte is opaque (full",
01172 "coverage) for pixels inside the shape, zero outside, and",
01173 "between 0 and QuantumRange on the boundary. If image does not",
01174 "have a matte channel, it is initialized with 0 for any pixel",
01175 "matching in color to pixel location (0,0), otherwise QuantumRange.",
01176 "",
01177 "Note that matte information for image window is not retained",
01178 "for colormapped X server visuals (e.g. StaticColor,",
01179 "StaticColor, GrayScale, PseudoColor). Correct compositing",
01180 "behavior may require a TrueColor or DirectColor visual or a",
01181 "Standard Colormap.",
01182 "",
01183 "Choosing a composite operator is optional. The default",
01184 "operator is replace. However, you must choose a location to",
01185 "paste your image and press button 1. Press and hold the",
01186 "button before releasing and an outline of the image will",
01187 "appear to help you identify your location.",
01188 "",
01189 "The actual colors of the pasted image is saved. However,",
01190 "the color that appears in image window may be different.",
01191 "For example, on a monochrome screen image window will appear",
01192 "black or white even though your pasted image may have",
01193 "many colors. If the image is saved to a file it is written",
01194 "with the correct colors. To assure the correct colors are",
01195 "saved in the final image, any PseudoClass image is promoted",
01196 "to DirectClass (see miff(5)). To force a PseudoClass image",
01197 "to remain PseudoClass, use -colors.",
01198 (char *) NULL,
01199 },
01200 *ImageROIHelp[] =
01201 {
01202 "In region of interest mode, the Command widget has these",
01203 "options:",
01204 "",
01205 " Help",
01206 " Dismiss",
01207 "",
01208 "To define a region of interest, press button 1 and drag.",
01209 "The region of interest is defined by a highlighted rectangle",
01210 "that expands or contracts as it follows the pointer. Once",
01211 "you are satisfied with the region of interest, release the",
01212 "button. You are now in apply mode. In apply mode the",
01213 "Command widget has these options:",
01214 "",
01215 " File",
01216 " Save...",
01217 " Print...",
01218 " Edit",
01219 " Undo",
01220 " Redo",
01221 " Transform",
01222 " Flop",
01223 " Flip",
01224 " Rotate Right",
01225 " Rotate Left",
01226 " Enhance",
01227 " Hue...",
01228 " Saturation...",
01229 " Brightness...",
01230 " Gamma...",
01231 " Spiff",
01232 " Dull",
01233 " Contrast Stretch",
01234 " Sigmoidal Contrast...",
01235 " Normalize",
01236 " Equalize",
01237 " Negate",
01238 " Grayscale",
01239 " Map...",
01240 " Quantize...",
01241 " Effects",
01242 " Despeckle",
01243 " Emboss",
01244 " Reduce Noise",
01245 " Sharpen...",
01246 " Blur...",
01247 " Threshold...",
01248 " Edge Detect...",
01249 " Spread...",
01250 " Shade...",
01251 " Raise...",
01252 " Segment...",
01253 " F/X",
01254 " Solarize...",
01255 " Sepia Tone...",
01256 " Swirl...",
01257 " Implode...",
01258 " Vignette...",
01259 " Wave...",
01260 " Oil Painting...",
01261 " Charcoal Drawing...",
01262 " Miscellany",
01263 " Image Info",
01264 " Zoom Image",
01265 " Show Preview...",
01266 " Show Histogram",
01267 " Show Matte",
01268 " Help",
01269 " Dismiss",
01270 "",
01271 "You can make adjustments to the region of interest by moving",
01272 "the pointer to one of the rectangle corners, pressing a",
01273 "button, and dragging. Finally, choose an image processing",
01274 "technique from the Command widget. You can choose more than",
01275 "one image processing technique to apply to an area.",
01276 "Alternatively, you can move the region of interest before",
01277 "applying another image processing technique. To exit, press",
01278 "Dismiss.",
01279 (char *) NULL,
01280 },
01281 *ImageRotateHelp[] =
01282 {
01283 "In rotate mode, the Command widget has these options:",
01284 "",
01285 " Pixel Color",
01286 " black",
01287 " blue",
01288 " cyan",
01289 " green",
01290 " gray",
01291 " red",
01292 " magenta",
01293 " yellow",
01294 " white",
01295 " Browser...",
01296 " Direction",
01297 " horizontal",
01298 " vertical",
01299 " Help",
01300 " Dismiss",
01301 "",
01302 "Choose a background color from the Pixel Color sub-menu.",
01303 "Additional background colors can be specified with the color",
01304 "browser. You can change the menu colors by setting the X",
01305 "resources pen1 through pen9.",
01306 "",
01307 "If you choose the color browser and press Grab, you can",
01308 "select the background color by moving the pointer to the",
01309 "desired color on the screen and press any button.",
01310 "",
01311 "Choose a point in the image window and press this button and",
01312 "hold. Next, move the pointer to another location in the",
01313 "image. As you move a line connects the initial location and",
01314 "the pointer. When you release the button, the degree of",
01315 "image rotation is determined by the slope of the line you",
01316 "just drew. The slope is relative to the direction you",
01317 "choose from the Direction sub-menu of the Command widget.",
01318 "",
01319 "To cancel the image rotation, move the pointer back to the",
01320 "starting point of the line and release the button.",
01321 (char *) NULL,
01322 };
01323
01324
01325
01326
01327 typedef enum
01328 {
01329 CopyMode,
01330 CropMode,
01331 CutMode
01332 } ClipboardMode;
01333
01334 typedef enum
01335 {
01336 OpenCommand,
01337 NextCommand,
01338 FormerCommand,
01339 SelectCommand,
01340 SaveCommand,
01341 PrintCommand,
01342 DeleteCommand,
01343 NewCommand,
01344 VisualDirectoryCommand,
01345 QuitCommand,
01346 UndoCommand,
01347 RedoCommand,
01348 CutCommand,
01349 CopyCommand,
01350 PasteCommand,
01351 HalfSizeCommand,
01352 OriginalSizeCommand,
01353 DoubleSizeCommand,
01354 ResizeCommand,
01355 ApplyCommand,
01356 RefreshCommand,
01357 RestoreCommand,
01358 CropCommand,
01359 ChopCommand,
01360 FlopCommand,
01361 FlipCommand,
01362 RotateRightCommand,
01363 RotateLeftCommand,
01364 RotateCommand,
01365 ShearCommand,
01366 RollCommand,
01367 TrimCommand,
01368 HueCommand,
01369 SaturationCommand,
01370 BrightnessCommand,
01371 GammaCommand,
01372 SpiffCommand,
01373 DullCommand,
01374 ContrastStretchCommand,
01375 SigmoidalContrastCommand,
01376 NormalizeCommand,
01377 EqualizeCommand,
01378 NegateCommand,
01379 GrayscaleCommand,
01380 MapCommand,
01381 QuantizeCommand,
01382 DespeckleCommand,
01383 EmbossCommand,
01384 ReduceNoiseCommand,
01385 AddNoiseCommand,
01386 SharpenCommand,
01387 BlurCommand,
01388 ThresholdCommand,
01389 EdgeDetectCommand,
01390 SpreadCommand,
01391 ShadeCommand,
01392 RaiseCommand,
01393 SegmentCommand,
01394 SolarizeCommand,
01395 SepiaToneCommand,
01396 SwirlCommand,
01397 ImplodeCommand,
01398 VignetteCommand,
01399 WaveCommand,
01400 OilPaintCommand,
01401 CharcoalDrawCommand,
01402 AnnotateCommand,
01403 DrawCommand,
01404 ColorCommand,
01405 MatteCommand,
01406 CompositeCommand,
01407 AddBorderCommand,
01408 AddFrameCommand,
01409 CommentCommand,
01410 LaunchCommand,
01411 RegionofInterestCommand,
01412 ROIHelpCommand,
01413 ROIDismissCommand,
01414 InfoCommand,
01415 ZoomCommand,
01416 ShowPreviewCommand,
01417 ShowHistogramCommand,
01418 ShowMatteCommand,
01419 BackgroundCommand,
01420 SlideShowCommand,
01421 PreferencesCommand,
01422 HelpCommand,
01423 BrowseDocumentationCommand,
01424 VersionCommand,
01425 SaveToUndoBufferCommand,
01426 FreeBuffersCommand,
01427 NullCommand
01428 } CommandType;
01429
01430 typedef enum
01431 {
01432 AnnotateNameCommand,
01433 AnnotateFontColorCommand,
01434 AnnotateBackgroundColorCommand,
01435 AnnotateRotateCommand,
01436 AnnotateHelpCommand,
01437 AnnotateDismissCommand,
01438 TextHelpCommand,
01439 TextApplyCommand,
01440 ChopDirectionCommand,
01441 ChopHelpCommand,
01442 ChopDismissCommand,
01443 HorizontalChopCommand,
01444 VerticalChopCommand,
01445 ColorEditMethodCommand,
01446 ColorEditColorCommand,
01447 ColorEditBorderCommand,
01448 ColorEditFuzzCommand,
01449 ColorEditUndoCommand,
01450 ColorEditHelpCommand,
01451 ColorEditDismissCommand,
01452 CompositeOperatorsCommand,
01453 CompositeDissolveCommand,
01454 CompositeDisplaceCommand,
01455 CompositeHelpCommand,
01456 CompositeDismissCommand,
01457 CropHelpCommand,
01458 CropDismissCommand,
01459 RectifyCopyCommand,
01460 RectifyHelpCommand,
01461 RectifyDismissCommand,
01462 DrawElementCommand,
01463 DrawColorCommand,
01464 DrawStippleCommand,
01465 DrawWidthCommand,
01466 DrawUndoCommand,
01467 DrawHelpCommand,
01468 DrawDismissCommand,
01469 MatteEditMethod,
01470 MatteEditBorderCommand,
01471 MatteEditFuzzCommand,
01472 MatteEditValueCommand,
01473 MatteEditUndoCommand,
01474 MatteEditHelpCommand,
01475 MatteEditDismissCommand,
01476 PasteOperatorsCommand,
01477 PasteHelpCommand,
01478 PasteDismissCommand,
01479 RotateColorCommand,
01480 RotateDirectionCommand,
01481 RotateCropCommand,
01482 RotateSharpenCommand,
01483 RotateHelpCommand,
01484 RotateDismissCommand,
01485 HorizontalRotateCommand,
01486 VerticalRotateCommand,
01487 TileLoadCommand,
01488 TileNextCommand,
01489 TileFormerCommand,
01490 TileDeleteCommand,
01491 TileUpdateCommand
01492 } ModeType;
01493
01494
01495
01496
01497 #define BricksWidth 20
01498 #define BricksHeight 20
01499 #define DiagonalWidth 16
01500 #define DiagonalHeight 16
01501 #define HighlightWidth 8
01502 #define HighlightHeight 8
01503 #define ScalesWidth 16
01504 #define ScalesHeight 16
01505 #define ShadowWidth 8
01506 #define ShadowHeight 8
01507 #define VerticalWidth 16
01508 #define VerticalHeight 16
01509 #define WavyWidth 16
01510 #define WavyHeight 16
01511
01512
01513
01514
01515 static const int
01516 RoiDelta = 8;
01517
01518 static const unsigned char
01519 BricksBitmap[] =
01520 {
01521 0xff, 0xff, 0x0f, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00,
01522 0x03, 0x0c, 0x00, 0xff, 0xff, 0x0f, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01,
01523 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0xff, 0xff, 0x0f, 0x03, 0x0c, 0x00,
01524 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0xff, 0xff, 0x0f,
01525 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01
01526 },
01527 DiagonalBitmap[] =
01528 {
01529 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22, 0x44, 0x44, 0x88, 0x88,
01530 0x11, 0x11, 0x22, 0x22, 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22,
01531 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22
01532 },
01533 ScalesBitmap[] =
01534 {
01535 0x08, 0x08, 0x08, 0x08, 0x14, 0x14, 0xe3, 0xe3, 0x80, 0x80, 0x80, 0x80,
01536 0x41, 0x41, 0x3e, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x14, 0x14, 0xe3, 0xe3,
01537 0x80, 0x80, 0x80, 0x80, 0x41, 0x41, 0x3e, 0x3e
01538 },
01539 VerticalBitmap[] =
01540 {
01541 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
01542 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
01543 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
01544 },
01545 WavyBitmap[] =
01546 {
01547 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfb, 0xff,
01548 0xe7, 0xff, 0x1f, 0xff, 0xff, 0xf8, 0xff, 0xe7, 0xff, 0xdf, 0xff, 0xbf,
01549 0xff, 0xbf, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f
01550 };
01551
01552
01553
01554
01555 static CommandType
01556 XImageWindowCommand(Display *,XResourceInfo *,XWindows *,
01557 const MagickStatusType,KeySym,Image **);
01558
01559 static Image
01560 *XMagickCommand(Display *,XResourceInfo *,XWindows *,const CommandType,
01561 Image **),
01562 *XOpenImage(Display *,XResourceInfo *,XWindows *,const MagickBooleanType),
01563 *XTileImage(Display *,XResourceInfo *,XWindows *,Image *,XEvent *),
01564 *XVisualDirectoryImage(Display *,XResourceInfo *,XWindows *);
01565
01566 static MagickBooleanType
01567 XAnnotateEditImage(Display *,XResourceInfo *,XWindows *,Image *),
01568 XDrawEditImage(Display *,XResourceInfo *,XWindows *,Image **),
01569 XChopImage(Display *,XResourceInfo *,XWindows *,Image **),
01570 XCropImage(Display *,XResourceInfo *,XWindows *,Image *,const ClipboardMode),
01571 XBackgroundImage(Display *,XResourceInfo *,XWindows *,Image **),
01572 XColorEditImage(Display *,XResourceInfo *,XWindows *,Image **),
01573 XCompositeImage(Display *,XResourceInfo *,XWindows *,Image *),
01574 XConfigureImage(Display *,XResourceInfo *,XWindows *,Image *),
01575 XMatteEditImage(Display *,XResourceInfo *,XWindows *,Image **),
01576 XPasteImage(Display *,XResourceInfo *,XWindows *,Image *),
01577 XPrintImage(Display *,XResourceInfo *,XWindows *,Image *),
01578 XRotateImage(Display *,XResourceInfo *,XWindows *,double,Image **),
01579 XROIImage(Display *,XResourceInfo *,XWindows *,Image **),
01580 XSaveImage(Display *,XResourceInfo *,XWindows *,Image *),
01581 XTrimImage(Display *,XResourceInfo *,XWindows *,Image *);
01582
01583 static void
01584 XDrawPanRectangle(Display *,XWindows *),
01585 XImageCache(Display *,XResourceInfo *,XWindows *,const CommandType,Image **),
01586 XMagnifyImage(Display *,XWindows *,XEvent *),
01587 XMakePanImage(Display *,XResourceInfo *,XWindows *,Image *),
01588 XPanImage(Display *,XWindows *,XEvent *),
01589 XMagnifyWindowCommand(Display *,XWindows *,const MagickStatusType,
01590 const KeySym),
01591 XSetCropGeometry(Display *,XWindows *,RectangleInfo *,Image *),
01592 XScreenEvent(Display *,XWindows *,XEvent *),
01593 XTranslateImage(Display *,XWindows *,Image *,const KeySym);
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
01622 MagickExport MagickBooleanType DisplayImages(const ImageInfo *image_info,
01623 Image *images)
01624 {
01625 char
01626 *argv[1];
01627
01628 Display
01629 *display;
01630
01631 Image
01632 *image;
01633
01634 register long
01635 i;
01636
01637 unsigned long
01638 state;
01639
01640 XrmDatabase
01641 resource_database;
01642
01643 XResourceInfo
01644 resource_info;
01645
01646 assert(image_info != (const ImageInfo *) NULL);
01647 assert(image_info->signature == MagickSignature);
01648 assert(images != (Image *) NULL);
01649 assert(images->signature == MagickSignature);
01650 if (images->debug != MagickFalse)
01651 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
01652 display=XOpenDisplay(image_info->server_name);
01653 if (display == (Display *) NULL)
01654 {
01655 (void) ThrowMagickException(&images->exception,GetMagickModule(),
01656 XServerError,"UnableToOpenXServer","`%s'",XDisplayName(
01657 image_info->server_name));
01658 return(MagickFalse);
01659 }
01660 if (images->exception.severity != UndefinedException)
01661 CatchException(&images->exception);
01662 (void) XSetErrorHandler(XError);
01663 resource_database=XGetResourceDatabase(display,GetClientName());
01664 (void) ResetMagickMemory(&resource_info,0,sizeof(resource_info));
01665 XGetResourceInfo(image_info,resource_database,GetClientName(),&resource_info);
01666 if (image_info->page != (char *) NULL)
01667 resource_info.image_geometry=AcquireString(image_info->page);
01668 resource_info.immutable=MagickTrue;
01669 argv[0]=AcquireString(GetClientName());
01670 state=DefaultState;
01671 for (i=0; (state & ExitState) == 0; i++)
01672 {
01673 if ((images->iterations != 0) && (i >= (long) images->iterations))
01674 break;
01675 image=GetImageFromList(images,i % GetImageListLength(images));
01676 (void) XDisplayImage(display,&resource_info,argv,1,&image,&state);
01677 }
01678 argv[0]=DestroyString(argv[0]);
01679 (void) XCloseDisplay(display);
01680 XDestroyResourceInfo(&resource_info);
01681 if (images->exception.severity != UndefinedException)
01682 return(MagickFalse);
01683 return(MagickTrue);
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
01716 MagickExport MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
01717 const char *window,const char *filename,ExceptionInfo *exception)
01718 {
01719 Display
01720 *display;
01721
01722 MagickStatusType
01723 status;
01724
01725 assert(image_info != (const ImageInfo *) NULL);
01726 assert(image_info->signature == MagickSignature);
01727 assert(filename != (char *) NULL);
01728 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
01729 display=XOpenDisplay(image_info->server_name);
01730 if (display == (Display *) NULL)
01731 {
01732 (void) ThrowMagickException(exception,GetMagickModule(),XServerError,
01733 "UnableToOpenXServer","`%s'",XDisplayName(image_info->server_name));
01734 return(MagickFalse);
01735 }
01736 (void) XSetErrorHandler(XError);
01737 status=XRemoteCommand(display,window,filename);
01738 (void) XCloseDisplay(display);
01739 return(status != 0 ? MagickTrue : MagickFalse);
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
01773 static inline long MagickMax(const long x,const long y)
01774 {
01775 if (x > y)
01776 return(x);
01777 return(y);
01778 }
01779
01780 static inline long MagickMin(const long x,const long y)
01781 {
01782 if (x < y)
01783 return(x);
01784 return(y);
01785 }
01786
01787 static MagickBooleanType XAnnotateEditImage(Display *display,
01788 XResourceInfo *resource_info,XWindows *windows,Image *image)
01789 {
01790 static const char
01791 *AnnotateMenu[] =
01792 {
01793 "Font Name",
01794 "Font Color",
01795 "Box Color",
01796 "Rotate Text",
01797 "Help",
01798 "Dismiss",
01799 (char *) NULL
01800 },
01801 *TextMenu[] =
01802 {
01803 "Help",
01804 "Apply",
01805 (char *) NULL
01806 };
01807
01808 static const ModeType
01809 AnnotateCommands[] =
01810 {
01811 AnnotateNameCommand,
01812 AnnotateFontColorCommand,
01813 AnnotateBackgroundColorCommand,
01814 AnnotateRotateCommand,
01815 AnnotateHelpCommand,
01816 AnnotateDismissCommand
01817 },
01818 TextCommands[] =
01819 {
01820 TextHelpCommand,
01821 TextApplyCommand
01822 };
01823
01824 static MagickBooleanType
01825 transparent_box = MagickTrue,
01826 transparent_pen = MagickFalse;
01827
01828 static MagickRealType
01829 degrees = 0.0;
01830
01831 static unsigned int
01832 box_id = MaxNumberPens-2,
01833 font_id = 0,
01834 pen_id = 0;
01835
01836 char
01837 command[MaxTextExtent],
01838 text[MaxTextExtent];
01839
01840 const char
01841 *ColorMenu[MaxNumberPens+1];
01842
01843 Cursor
01844 cursor;
01845
01846 GC
01847 annotate_context;
01848
01849 int
01850 id,
01851 pen_number,
01852 status,
01853 x,
01854 y;
01855
01856 KeySym
01857 key_symbol;
01858
01859 register char
01860 *p;
01861
01862 register long
01863 i;
01864
01865 unsigned int
01866 height,
01867 width;
01868
01869 unsigned long
01870 state;
01871
01872 XAnnotateInfo
01873 *annotate_info,
01874 *previous_info;
01875
01876 XColor
01877 color;
01878
01879 XFontStruct
01880 *font_info;
01881
01882 XEvent
01883 event,
01884 text_event;
01885
01886
01887
01888
01889 (void) CloneString(&windows->command.name,"Annotate");
01890 windows->command.data=4;
01891 (void) XCommandWidget(display,windows,AnnotateMenu,(XEvent *) NULL);
01892 (void) XMapRaised(display,windows->command.id);
01893 XClientMessage(display,windows->image.id,windows->im_protocols,
01894 windows->im_update_widget,CurrentTime);
01895
01896
01897
01898 XQueryPosition(display,windows->image.id,&x,&y);
01899 (void) XSelectInput(display,windows->image.id,
01900 windows->image.attributes.event_mask | PointerMotionMask);
01901 cursor=XCreateFontCursor(display,XC_left_side);
01902 (void) XCheckDefineCursor(display,windows->image.id,cursor);
01903 state=DefaultState;
01904 do
01905 {
01906 if (windows->info.mapped != MagickFalse)
01907 {
01908
01909
01910
01911 (void) FormatMagickString(text,MaxTextExtent," %+d%+d ",
01912 x+windows->image.x,y+windows->image.y);
01913 XInfoWidget(display,windows,text);
01914 }
01915
01916
01917
01918 XScreenEvent(display,windows,&event);
01919 if (event.xany.window == windows->command.id)
01920 {
01921
01922
01923
01924 id=XCommandWidget(display,windows,AnnotateMenu,&event);
01925 (void) XCheckDefineCursor(display,windows->image.id,cursor);
01926 if (id < 0)
01927 continue;
01928 switch (AnnotateCommands[id])
01929 {
01930 case AnnotateNameCommand:
01931 {
01932 const char
01933 *FontMenu[MaxNumberFonts];
01934
01935 int
01936 font_number;
01937
01938
01939
01940
01941 for (i=0; i < MaxNumberFonts; i++)
01942 FontMenu[i]=resource_info->font_name[i];
01943 FontMenu[MaxNumberFonts-2]="Browser...";
01944 FontMenu[MaxNumberFonts-1]=(const char *) NULL;
01945
01946
01947
01948 font_number=XMenuWidget(display,windows,AnnotateMenu[id],
01949 (const char **) FontMenu,command);
01950 if (font_number < 0)
01951 break;
01952 if (font_number == (MaxNumberFonts-2))
01953 {
01954 static char
01955 font_name[MaxTextExtent] = "fixed";
01956
01957
01958
01959
01960 resource_info->font_name[font_number]=font_name;
01961 XFontBrowserWidget(display,windows,"Select",font_name);
01962 if (*font_name == '\0')
01963 break;
01964 }
01965
01966
01967
01968 font_info=XLoadQueryFont(display,resource_info->font_name[
01969 font_number]);
01970 if (font_info == (XFontStruct *) NULL)
01971 {
01972 XNoticeWidget(display,windows,"Unable to load font:",
01973 resource_info->font_name[font_number]);
01974 break;
01975 }
01976 font_id=(unsigned int) font_number;
01977 (void) XFreeFont(display,font_info);
01978 break;
01979 }
01980 case AnnotateFontColorCommand:
01981 {
01982
01983
01984
01985 for (i=0; i < (int) (MaxNumberPens-2); i++)
01986 ColorMenu[i]=resource_info->pen_colors[i];
01987 ColorMenu[MaxNumberPens-2]="transparent";
01988 ColorMenu[MaxNumberPens-1]="Browser...";
01989 ColorMenu[MaxNumberPens]=(const char *) NULL;
01990
01991
01992
01993 pen_number=XMenuWidget(display,windows,AnnotateMenu[id],
01994 (const char **) ColorMenu,command);
01995 if (pen_number < 0)
01996 break;
01997 transparent_pen=pen_number == (MaxNumberPens-2) ? MagickTrue :
01998 MagickFalse;
01999 if (transparent_pen != MagickFalse)
02000 break;
02001 if (pen_number == (MaxNumberPens-1))
02002 {
02003 static char
02004 color_name[MaxTextExtent] = "gray";
02005
02006
02007
02008
02009 resource_info->pen_colors[pen_number]=color_name;
02010 XColorBrowserWidget(display,windows,"Select",color_name);
02011 if (*color_name == '\0')
02012 break;
02013 }
02014
02015
02016
02017 (void) XParseColor(display,windows->map_info->colormap,
02018 resource_info->pen_colors[pen_number],&color);
02019 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
02020 (unsigned int) MaxColors,&color);
02021 windows->pixel_info->pen_colors[pen_number]=color;
02022 pen_id=(unsigned int) pen_number;
02023 break;
02024 }
02025 case AnnotateBackgroundColorCommand:
02026 {
02027
02028
02029
02030 for (i=0; i < (int) (MaxNumberPens-2); i++)
02031 ColorMenu[i]=resource_info->pen_colors[i];
02032 ColorMenu[MaxNumberPens-2]="transparent";
02033 ColorMenu[MaxNumberPens-1]="Browser...";
02034 ColorMenu[MaxNumberPens]=(const char *) NULL;
02035
02036
02037
02038 pen_number=XMenuWidget(display,windows,AnnotateMenu[id],
02039 (const char **) ColorMenu,command);
02040 if (pen_number < 0)
02041 break;
02042 transparent_box=pen_number == (MaxNumberPens-2) ? MagickTrue :
02043 MagickFalse;
02044 if (transparent_box != MagickFalse)
02045 break;
02046 if (pen_number == (MaxNumberPens-1))
02047 {
02048 static char
02049 color_name[MaxTextExtent] = "gray";
02050
02051
02052
02053
02054 resource_info->pen_colors[pen_number]=color_name;
02055 XColorBrowserWidget(display,windows,"Select",color_name);
02056 if (*color_name == '\0')
02057 break;
02058 }
02059
02060
02061
02062 (void) XParseColor(display,windows->map_info->colormap,
02063 resource_info->pen_colors[pen_number],&color);
02064 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
02065 (unsigned int) MaxColors,&color);
02066 windows->pixel_info->pen_colors[pen_number]=color;
02067 box_id=(unsigned int) pen_number;
02068 break;
02069 }
02070 case AnnotateRotateCommand:
02071 {
02072 int
02073 entry;
02074
02075 static char
02076 angle[MaxTextExtent] = "30.0";
02077
02078 static const char
02079 *RotateMenu[] =
02080 {
02081 "-90",
02082 "-45",
02083 "-30",
02084 "0",
02085 "30",
02086 "45",
02087 "90",
02088 "180",
02089 "Dialog...",
02090 (char *) NULL,
02091 };
02092
02093
02094
02095
02096 entry=XMenuWidget(display,windows,AnnotateMenu[id],RotateMenu,
02097 command);
02098 if (entry < 0)
02099 break;
02100 if (entry != 8)
02101 {
02102 degrees=StringToDouble(RotateMenu[entry]);
02103 break;
02104 }
02105 (void) XDialogWidget(display,windows,"OK","Enter rotation angle:",
02106 angle);
02107 if (*angle == '\0')
02108 break;
02109 degrees=StringToDouble(angle);
02110 break;
02111 }
02112 case AnnotateHelpCommand:
02113 {
02114 XTextViewWidget(display,resource_info,windows,MagickFalse,
02115 "Help Viewer - Image Annotation",ImageAnnotateHelp);
02116 break;
02117 }
02118 case AnnotateDismissCommand:
02119 {
02120
02121
02122
02123 state|=EscapeState;
02124 state|=ExitState;
02125 break;
02126 }
02127 default:
02128 break;
02129 }
02130 continue;
02131 }
02132 switch (event.type)
02133 {
02134 case ButtonPress:
02135 {
02136 if (event.xbutton.button != Button1)
02137 break;
02138 if (event.xbutton.window != windows->image.id)
02139 break;
02140
02141
02142
02143 x=event.xbutton.x;
02144 y=event.xbutton.y;
02145 state|=ExitState;
02146 break;
02147 }
02148 case ButtonRelease:
02149 break;
02150 case Expose:
02151 break;
02152 case KeyPress:
02153 {
02154 if (event.xkey.window != windows->image.id)
02155 break;
02156
02157
02158
02159 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
02160 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
02161 switch ((int) key_symbol)
02162 {
02163 case XK_Escape:
02164 case XK_F20:
02165 {
02166
02167
02168
02169 state|=EscapeState;
02170 state|=ExitState;
02171 break;
02172 }
02173 case XK_F1:
02174 case XK_Help:
02175 {
02176 XTextViewWidget(display,resource_info,windows,MagickFalse,
02177 "Help Viewer - Image Annotation",ImageAnnotateHelp);
02178 break;
02179 }
02180 default:
02181 {
02182 (void) XBell(display,0);
02183 break;
02184 }
02185 }
02186 break;
02187 }
02188 case MotionNotify:
02189 {
02190
02191
02192
02193 x=event.xmotion.x;
02194 y=event.xmotion.y;
02195 if (windows->info.mapped != MagickFalse)
02196 {
02197 if ((x < (int) (windows->info.x+windows->info.width)) &&
02198 (y < (int) (windows->info.y+windows->info.height)))
02199 (void) XWithdrawWindow(display,windows->info.id,
02200 windows->info.screen);
02201 }
02202 else
02203 if ((x > (int) (windows->info.x+windows->info.width)) ||
02204 (y > (int) (windows->info.y+windows->info.height)))
02205 (void) XMapWindow(display,windows->info.id);
02206 break;
02207 }
02208 default:
02209 break;
02210 }
02211 } while ((state & ExitState) == 0);
02212 (void) XSelectInput(display,windows->image.id,
02213 windows->image.attributes.event_mask);
02214 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
02215 if ((state & EscapeState) != 0)
02216 return(MagickTrue);
02217
02218
02219
02220 font_info=XLoadQueryFont(display,resource_info->font_name[font_id]);
02221 if (font_info == (XFontStruct *) NULL)
02222 {
02223 XNoticeWidget(display,windows,"Unable to load font:",
02224 resource_info->font_name[font_id]);
02225 font_info=windows->font_info;
02226 }
02227 if ((x+font_info->max_bounds.width) >= (int) windows->image.width)
02228 x=(int) windows->image.width-font_info->max_bounds.width;
02229 if (y < (int) (font_info->ascent+font_info->descent))
02230 y=(int) font_info->ascent+font_info->descent;
02231 if (((int) font_info->max_bounds.width > (int) windows->image.width) ||
02232 ((font_info->ascent+font_info->descent) >= (int) windows->image.height))
02233 return(MagickFalse);
02234
02235
02236
02237 annotate_info=(XAnnotateInfo *) AcquireAlignedMemory(1,sizeof(*annotate_info));
02238 if (annotate_info == (XAnnotateInfo *) NULL)
02239 return(MagickFalse);
02240 XGetAnnotateInfo(annotate_info);
02241 annotate_info->x=x;
02242 annotate_info->y=y;
02243 if ((transparent_box == MagickFalse) && (transparent_pen == MagickFalse))
02244 annotate_info->stencil=OpaqueStencil;
02245 else
02246 if (transparent_box == MagickFalse)
02247 annotate_info->stencil=BackgroundStencil;
02248 else
02249 annotate_info->stencil=ForegroundStencil;
02250 annotate_info->height=(unsigned int) font_info->ascent+font_info->descent;
02251 annotate_info->degrees=degrees;
02252 annotate_info->font_info=font_info;
02253 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
02254 windows->image.width/MagickMax(font_info->min_bounds.width,1)+2UL,
02255 sizeof(*annotate_info->text));
02256 if (annotate_info->text == (char *) NULL)
02257 return(MagickFalse);
02258
02259
02260
02261 cursor=XCreateFontCursor(display,XC_pencil);
02262 (void) XCheckDefineCursor(display,windows->image.id,cursor);
02263 annotate_context=windows->image.annotate_context;
02264 (void) XSetFont(display,annotate_context,font_info->fid);
02265 (void) XSetBackground(display,annotate_context,
02266 windows->pixel_info->pen_colors[box_id].pixel);
02267 (void) XSetForeground(display,annotate_context,
02268 windows->pixel_info->pen_colors[pen_id].pixel);
02269
02270
02271
02272 (void) CloneString(&windows->command.name,"Text");
02273 windows->command.data=0;
02274 (void) XCommandWidget(display,windows,TextMenu,(XEvent *) NULL);
02275 state=DefaultState;
02276 (void) XDrawString(display,windows->image.id,annotate_context,x,y,"_",1);
02277 text_event.xexpose.width=(int) font_info->max_bounds.width;
02278 text_event.xexpose.height=font_info->max_bounds.ascent+
02279 font_info->max_bounds.descent;
02280 p=annotate_info->text;
02281 do
02282 {
02283
02284
02285
02286 *p='\0';
02287 (void) XDrawString(display,windows->image.id,annotate_context,x,y,"_",1);
02288
02289
02290
02291 XScreenEvent(display,windows,&event);
02292 if (event.xany.window == windows->command.id)
02293 {
02294
02295
02296
02297 (void) XSetBackground(display,annotate_context,
02298 windows->pixel_info->background_color.pixel);
02299 (void) XSetForeground(display,annotate_context,
02300 windows->pixel_info->foreground_color.pixel);
02301 id=XCommandWidget(display,windows,AnnotateMenu,&event);
02302 (void) XSetBackground(display,annotate_context,
02303 windows->pixel_info->pen_colors[box_id].pixel);
02304 (void) XSetForeground(display,annotate_context,
02305 windows->pixel_info->pen_colors[pen_id].pixel);
02306 if (id < 0)
02307 continue;
02308 switch (TextCommands[id])
02309 {
02310 case TextHelpCommand:
02311 {
02312 XTextViewWidget(display,resource_info,windows,MagickFalse,
02313 "Help Viewer - Image Annotation",ImageAnnotateHelp);
02314 (void) XCheckDefineCursor(display,windows->image.id,cursor);
02315 break;
02316 }
02317 case TextApplyCommand:
02318 {
02319
02320
02321
02322 annotate_info->width=(unsigned int) XTextWidth(font_info,
02323 annotate_info->text,(int) strlen(annotate_info->text));
02324 XRefreshWindow(display,&windows->image,&text_event);
02325 state|=ExitState;
02326 break;
02327 }
02328 default:
02329 break;
02330 }
02331 continue;
02332 }
02333
02334
02335
02336 text_event.xexpose.x=x;
02337 text_event.xexpose.y=y-font_info->max_bounds.ascent;
02338 (void) XClearArea(display,windows->image.id,x,text_event.xexpose.y,
02339 (unsigned int) text_event.xexpose.width,(unsigned int)
02340 text_event.xexpose.height,MagickFalse);
02341 XRefreshWindow(display,&windows->image,&text_event);
02342 switch (event.type)
02343 {
02344 case ButtonPress:
02345 {
02346 if (event.xbutton.window != windows->image.id)
02347 break;
02348 if (event.xbutton.button == Button2)
02349 {
02350
02351
02352
02353 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
02354 windows->image.id,CurrentTime);
02355 break;
02356 }
02357 break;
02358 }
02359 case Expose:
02360 {
02361 if (event.xexpose.count == 0)
02362 {
02363 XAnnotateInfo
02364 *text_info;
02365
02366
02367
02368
02369 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
02370 text_info=annotate_info;
02371 while (text_info != (XAnnotateInfo *) NULL)
02372 {
02373 if (annotate_info->stencil == ForegroundStencil)
02374 (void) XDrawString(display,windows->image.id,annotate_context,
02375 text_info->x,text_info->y,text_info->text,
02376 (int) strlen(text_info->text));
02377 else
02378 (void) XDrawImageString(display,windows->image.id,
02379 annotate_context,text_info->x,text_info->y,text_info->text,
02380 (int) strlen(text_info->text));
02381 text_info=text_info->previous;
02382 }
02383 (void) XDrawString(display,windows->image.id,annotate_context,
02384 x,y,"_",1);
02385 }
02386 break;
02387 }
02388 case KeyPress:
02389 {
02390 int
02391 length;
02392
02393 if (event.xkey.window != windows->image.id)
02394 break;
02395
02396
02397
02398 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
02399 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
02400 *(command+length)='\0';
02401 if (((event.xkey.state & ControlMask) != 0) ||
02402 ((event.xkey.state & Mod1Mask) != 0))
02403 state|=ModifierState;
02404 if ((state & ModifierState) != 0)
02405 switch ((int) key_symbol)
02406 {
02407 case XK_u:
02408 case XK_U:
02409 {
02410 key_symbol=DeleteCommand;
02411 break;
02412 }
02413 default:
02414 break;
02415 }
02416 switch ((int) key_symbol)
02417 {
02418 case XK_BackSpace:
02419 {
02420
02421
02422
02423 if (p == annotate_info->text)
02424 {
02425 if (annotate_info->previous == (XAnnotateInfo *) NULL)
02426 break;
02427 else
02428 {
02429
02430
02431
02432 annotate_info=annotate_info->previous;
02433 p=annotate_info->text;
02434 x=annotate_info->x+annotate_info->width;
02435 y=annotate_info->y;
02436 if (annotate_info->width != 0)
02437 p+=strlen(annotate_info->text);
02438 break;
02439 }
02440 }
02441 p--;
02442 x-=XTextWidth(font_info,p,1);
02443 text_event.xexpose.x=x;
02444 text_event.xexpose.y=y-font_info->max_bounds.ascent;
02445 XRefreshWindow(display,&windows->image,&text_event);
02446 break;
02447 }
02448 case XK_bracketleft:
02449 {
02450 key_symbol=XK_Escape;
02451 break;
02452 }
02453 case DeleteCommand:
02454 {
02455
02456
02457
02458 while (p != annotate_info->text)
02459 {
02460 p--;
02461 x-=XTextWidth(font_info,p,1);
02462 text_event.xexpose.x=x;
02463 XRefreshWindow(display,&windows->image,&text_event);
02464 }
02465 break;
02466 }
02467 case XK_Escape:
02468 case XK_F20:
02469 {
02470
02471
02472
02473 annotate_info->width=(unsigned int) XTextWidth(font_info,
02474 annotate_info->text,(int) strlen(annotate_info->text));
02475 XRefreshWindow(display,&windows->image,&text_event);
02476 state|=ExitState;
02477 break;
02478 }
02479 default:
02480 {
02481
02482
02483
02484 if ((state & ModifierState) != 0)
02485 break;
02486 if (*command == '\0')
02487 break;
02488 *p=(*command);
02489 if (annotate_info->stencil == ForegroundStencil)
02490 (void) XDrawString(display,windows->image.id,annotate_context,
02491 x,y,p,1);
02492 else
02493 (void) XDrawImageString(display,windows->image.id,
02494 annotate_context,x,y,p,1);
02495 x+=XTextWidth(font_info,p,1);
02496 p++;
02497 if ((x+font_info->max_bounds.width) < (int) windows->image.width)
02498 break;
02499 }
02500 case XK_Return:
02501 case XK_KP_Enter:
02502 {
02503
02504
02505
02506 *p='\0';
02507 annotate_info->width=(unsigned int) XTextWidth(font_info,
02508 annotate_info->text,(int) strlen(annotate_info->text));
02509 if (annotate_info->next != (XAnnotateInfo *) NULL)
02510 {
02511
02512
02513
02514 annotate_info=annotate_info->next;
02515 x=annotate_info->x;
02516 y=annotate_info->y;
02517 p=annotate_info->text;
02518 break;
02519 }
02520 annotate_info->next=(XAnnotateInfo *) AcquireMagickMemory(
02521 sizeof(*annotate_info->next));
02522 if (annotate_info->next == (XAnnotateInfo *) NULL)
02523 return(MagickFalse);
02524 *annotate_info->next=(*annotate_info);
02525 annotate_info->next->previous=annotate_info;
02526 annotate_info=annotate_info->next;
02527 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
02528 windows->image.width/MagickMax(font_info->min_bounds.width,1)+2UL,
02529 sizeof(*annotate_info->text));
02530 if (annotate_info->text == (char *) NULL)
02531 return(MagickFalse);
02532 annotate_info->y+=annotate_info->height;
02533 if (annotate_info->y > (int) windows->image.height)
02534 annotate_info->y=(int) annotate_info->height;
02535 annotate_info->next=(XAnnotateInfo *) NULL;
02536 x=annotate_info->x;
02537 y=annotate_info->y;
02538 p=annotate_info->text;
02539 break;
02540 }
02541 }
02542 break;
02543 }
02544 case KeyRelease:
02545 {
02546
02547
02548
02549 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
02550 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
02551 state&=(~ModifierState);
02552 break;
02553 }
02554 case SelectionNotify:
02555 {
02556 Atom
02557 type;
02558
02559 int
02560 format;
02561
02562 unsigned char
02563 *data;
02564
02565 unsigned long
02566 after,
02567 length;
02568
02569
02570
02571
02572 if (event.xselection.property == (Atom) None)
02573 break;
02574 status=XGetWindowProperty(display,event.xselection.requestor,
02575 event.xselection.property,0L,(long) MaxTextExtent,True,XA_STRING,
02576 &type,&format,&length,&after,&data);
02577 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
02578 (length == 0))
02579 break;
02580
02581
02582
02583 for (i=0; i < (long) length; i++)
02584 {
02585 if ((char) data[i] != '\n')
02586 {
02587
02588
02589
02590 *p=(char) data[i];
02591 (void) XDrawString(display,windows->image.id,annotate_context,
02592 x,y,p,1);
02593 x+=XTextWidth(font_info,p,1);
02594 p++;
02595 if ((x+font_info->max_bounds.width) < (int) windows->image.width)
02596 continue;
02597 }
02598
02599
02600
02601 *p='\0';
02602 annotate_info->width=(unsigned int) XTextWidth(font_info,
02603 annotate_info->text,(int) strlen(annotate_info->text));
02604 if (annotate_info->next != (XAnnotateInfo *) NULL)
02605 {
02606
02607
02608
02609 annotate_info=annotate_info->next;
02610 x=annotate_info->x;
02611 y=annotate_info->y;
02612 p=annotate_info->text;
02613 continue;
02614 }
02615 annotate_info->next=(XAnnotateInfo *) AcquireMagickMemory(
02616 sizeof(*annotate_info->next));
02617 if (annotate_info->next == (XAnnotateInfo *) NULL)
02618 return(MagickFalse);
02619 *annotate_info->next=(*annotate_info);
02620 annotate_info->next->previous=annotate_info;
02621 annotate_info=annotate_info->next;
02622 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
02623 windows->image.width/MagickMax(font_info->min_bounds.width,1)+2UL,
02624 sizeof(*annotate_info->text));
02625 if (annotate_info->text == (char *) NULL)
02626 return(MagickFalse);
02627 annotate_info->y+=annotate_info->height;
02628 if (annotate_info->y > (int) windows->image.height)
02629 annotate_info->y=(int) annotate_info->height;
02630 annotate_info->next=(XAnnotateInfo *) NULL;
02631 x=annotate_info->x;
02632 y=annotate_info->y;
02633 p=annotate_info->text;
02634 }
02635 (void) XFree((void *) data);
02636 break;
02637 }
02638 default:
02639 break;
02640 }
02641 } while ((state & ExitState) == 0);
02642 (void) XFreeCursor(display,cursor);
02643
02644
02645
02646 width=(unsigned int) image->columns;
02647 height=(unsigned int) image->rows;
02648 x=0;
02649 y=0;
02650 if (windows->image.crop_geometry != (char *) NULL)
02651 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
02652
02653
02654
02655 XSetCursorState(display,windows,MagickTrue);
02656 XCheckRefreshWindows(display,windows);
02657 while (annotate_info != (XAnnotateInfo *) NULL)
02658 {
02659 if (annotate_info->width == 0)
02660 {
02661
02662
02663
02664 previous_info=annotate_info->previous;
02665 annotate_info->text=(char *)
02666 RelinquishMagickMemory(annotate_info->text);
02667 annotate_info=(XAnnotateInfo *) RelinquishMagickMemory(annotate_info);
02668 annotate_info=previous_info;
02669 continue;
02670 }
02671
02672
02673
02674 windows->pixel_info->box_color=windows->pixel_info->pen_colors[box_id];
02675 if (windows->pixel_info->colors != 0)
02676 for (i=0; i < (long) windows->pixel_info->colors; i++)
02677 if (windows->pixel_info->pixels[i] ==
02678 windows->pixel_info->pen_colors[box_id].pixel)
02679 {
02680 windows->pixel_info->box_index=(unsigned short) i;
02681 break;
02682 }
02683 windows->pixel_info->pen_color=windows->pixel_info->pen_colors[pen_id];
02684 if (windows->pixel_info->colors != 0)
02685 for (i=0; i < (long) windows->pixel_info->colors; i++)
02686 if (windows->pixel_info->pixels[i] ==
02687 windows->pixel_info->pen_colors[pen_id].pixel)
02688 {
02689 windows->pixel_info->pen_index=(unsigned short) i;
02690 break;
02691 }
02692
02693
02694
02695 annotate_info->x=(int)
02696 width*(annotate_info->x+windows->image.x)/windows->image.ximage->width;
02697 annotate_info->y=(int) height*(annotate_info->y-font_info->ascent+
02698 windows->image.y)/windows->image.ximage->height;
02699 (void) FormatMagickString(annotate_info->geometry,MaxTextExtent,
02700 "%ux%u%+d%+d",width*annotate_info->width/windows->image.ximage->width,
02701 height*annotate_info->height/windows->image.ximage->height,
02702 annotate_info->x+x,annotate_info->y+y);
02703
02704
02705
02706 status=XAnnotateImage(display,windows->pixel_info,annotate_info,image);
02707 if (status == 0)
02708 return(MagickFalse);
02709
02710
02711
02712 previous_info=annotate_info->previous;
02713 annotate_info->text=DestroyString(annotate_info->text);
02714 annotate_info=(XAnnotateInfo *) RelinquishMagickMemory(annotate_info);
02715 annotate_info=previous_info;
02716 }
02717 (void) XSetForeground(display,annotate_context,
02718 windows->pixel_info->foreground_color.pixel);
02719 (void) XSetBackground(display,annotate_context,
02720 windows->pixel_info->background_color.pixel);
02721 (void) XSetFont(display,annotate_context,windows->font_info->fid);
02722 XSetCursorState(display,windows,MagickFalse);
02723 (void) XFreeFont(display,font_info);
02724
02725
02726
02727 XConfigureImageColormap(display,resource_info,windows,image);
02728 (void) XConfigureImage(display,resource_info,windows,image);
02729 return(MagickTrue);
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
02762 static MagickBooleanType XBackgroundImage(Display *display,
02763 XResourceInfo *resource_info,XWindows *windows,Image **image)
02764 {
02765 #define BackgroundImageTag "Background/Image"
02766
02767 int
02768 status;
02769
02770 static char
02771 window_id[MaxTextExtent] = "root";
02772
02773 XResourceInfo
02774 background_resources;
02775
02776
02777
02778
02779 status=XDialogWidget(display,windows,"Background",
02780 "Enter window id (id 0x00 selects window with pointer):",window_id);
02781 if (*window_id == '\0')
02782 return(MagickFalse);
02783 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image);
02784 XInfoWidget(display,windows,BackgroundImageTag);
02785 XSetCursorState(display,windows,MagickTrue);
02786 XCheckRefreshWindows(display,windows);
02787 background_resources=(*resource_info);
02788 background_resources.window_id=window_id;
02789 background_resources.backdrop=status != 0 ? MagickTrue : MagickFalse;
02790 status=XDisplayBackgroundImage(display,&background_resources,*image);
02791 if (status != MagickFalse)
02792 XClientMessage(display,windows->image.id,windows->im_protocols,
02793 windows->im_retain_colors,CurrentTime);
02794 XSetCursorState(display,windows,MagickFalse);
02795 (void) XMagickCommand(display,resource_info,windows,UndoCommand,image);
02796 return(MagickTrue);
02797 }
02798
02799
02800
02801
02802
02803
02804
02805
02806
02807
02808
02809
02810
02811
02812
02813
02814
02815
02816
02817
02818
02819
02820
02821
02822
02823
02824
02825
02826
02827
02828
02829 static MagickBooleanType XChopImage(Display *display,
02830 XResourceInfo *resource_info,XWindows *windows,Image **image)
02831 {
02832 static const char
02833 *ChopMenu[] =
02834 {
02835 "Direction",
02836 "Help",
02837 "Dismiss",
02838 (char *) NULL
02839 };
02840
02841 static ModeType
02842 direction = HorizontalChopCommand;
02843
02844 static const ModeType
02845 ChopCommands[] =
02846 {
02847 ChopDirectionCommand,
02848 ChopHelpCommand,
02849 ChopDismissCommand
02850 },
02851 DirectionCommands[] =
02852 {
02853 HorizontalChopCommand,
02854 VerticalChopCommand
02855 };
02856
02857 char
02858 text[MaxTextExtent];
02859
02860 Image
02861 *chop_image;
02862
02863 int
02864 id,
02865 x,
02866 y;
02867
02868 MagickRealType
02869 scale_factor;
02870
02871 RectangleInfo
02872 chop_info;
02873
02874 unsigned int
02875 distance,
02876 height,
02877 width;
02878
02879 unsigned long
02880 state;
02881
02882 XEvent
02883 event;
02884
02885 XSegment
02886 segment_info;
02887
02888
02889
02890
02891 (void) CloneString(&windows->command.name,"Chop");
02892 windows->command.data=1;
02893 (void) XCommandWidget(display,windows,ChopMenu,(XEvent *) NULL);
02894 (void) XMapRaised(display,windows->command.id);
02895 XClientMessage(display,windows->image.id,windows->im_protocols,
02896 windows->im_update_widget,CurrentTime);
02897
02898
02899
02900 XQueryPosition(display,windows->image.id,&x,&y);
02901 (void) XSelectInput(display,windows->image.id,
02902 windows->image.attributes.event_mask | PointerMotionMask);
02903 state=DefaultState;
02904 do
02905 {
02906 if (windows->info.mapped != MagickFalse)
02907 {
02908
02909
02910
02911 (void) FormatMagickString(text,MaxTextExtent," %+d%+d ",
02912 x+windows->image.x,y+windows->image.y);
02913 XInfoWidget(display,windows,text);
02914 }
02915
02916
02917
02918 XScreenEvent(display,windows,&event);
02919 if (event.xany.window == windows->command.id)
02920 {
02921
02922
02923
02924 id=XCommandWidget(display,windows,ChopMenu,&event);
02925 if (id < 0)
02926 continue;
02927 switch (ChopCommands[id])
02928 {
02929 case ChopDirectionCommand:
02930 {
02931 char
02932 command[MaxTextExtent];
02933
02934 static const char
02935 *Directions[] =
02936 {
02937 "horizontal",
02938 "vertical",
02939 (char *) NULL,
02940 };
02941
02942
02943
02944
02945 id=XMenuWidget(display,windows,ChopMenu[id],Directions,command);
02946 if (id >= 0)
02947 direction=DirectionCommands[id];
02948 break;
02949 }
02950 case ChopHelpCommand:
02951 {
02952 XTextViewWidget(display,resource_info,windows,MagickFalse,
02953 "Help Viewer - Image Chop",ImageChopHelp);
02954 break;
02955 }
02956 case ChopDismissCommand:
02957 {
02958
02959
02960
02961 state|=EscapeState;
02962 state|=ExitState;
02963 break;
02964 }
02965 default:
02966 break;
02967 }
02968 continue;
02969 }
02970 switch (event.type)
02971 {
02972 case ButtonPress:
02973 {
02974 if (event.xbutton.button != Button1)
02975 break;
02976 if (event.xbutton.window != windows->image.id)
02977 break;
02978
02979
02980
02981 segment_info.x1=(short int) event.xbutton.x;
02982 segment_info.x2=(short int) event.xbutton.x;
02983 segment_info.y1=(short int) event.xbutton.y;
02984 segment_info.y2=(short int) event.xbutton.y;
02985 state|=ExitState;
02986 break;
02987 }
02988 case ButtonRelease:
02989 break;
02990 case Expose:
02991 break;
02992 case KeyPress:
02993 {
02994 char
02995 command[MaxTextExtent];
02996
02997 KeySym
02998 key_symbol;
02999
03000 if (event.xkey.window != windows->image.id)
03001 break;
03002
03003
03004
03005 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
03006 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
03007 switch ((int) key_symbol)
03008 {
03009 case XK_Escape:
03010 case XK_F20:
03011 {
03012
03013
03014
03015 state|=EscapeState;
03016 state|=ExitState;
03017 break;
03018 }
03019 case XK_F1:
03020 case XK_Help:
03021 {
03022 (void) XSetFunction(display,windows->image.highlight_context,
03023 GXcopy);
03024 XTextViewWidget(display,resource_info,windows,MagickFalse,
03025 "Help Viewer - Image Chop",ImageChopHelp);
03026 (void) XSetFunction(display,windows->image.highlight_context,
03027 GXinvert);
03028 break;
03029 }
03030 default:
03031 {
03032 (void) XBell(display,0);
03033 break;
03034 }
03035 }
03036 break;
03037 }
03038 case MotionNotify:
03039 {
03040
03041
03042
03043 x=event.xmotion.x;
03044 y=event.xmotion.y;
03045 if (windows->info.mapped != MagickFalse)
03046 {
03047 if ((x < (int) (windows->info.x+windows->info.width)) &&
03048 (y < (int) (windows->info.y+windows->info.height)))
03049 (void) XWithdrawWindow(display,windows->info.id,
03050 windows->info.screen);
03051 }
03052 else
03053 if ((x > (int) (windows->info.x+windows->info.width)) ||
03054 (y > (int) (windows->info.y+windows->info.height)))
03055 (void) XMapWindow(display,windows->info.id);
03056 }
03057 }
03058 } while ((state & ExitState) == 0);
03059 (void) XSelectInput(display,windows->image.id,
03060 windows->image.attributes.event_mask);
03061 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
03062 if ((state & EscapeState) != 0)
03063 return(MagickTrue);
03064
03065
03066
03067 chop_info.width=0;
03068 chop_info.height=0;
03069 chop_info.x=0;
03070 chop_info.y=0;
03071 distance=0;
03072 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
03073 state=DefaultState;
03074 do
03075 {
03076 if (distance > 9)
03077 {
03078
03079
03080
03081 if (windows->info.mapped == MagickFalse)
03082 (void) XMapWindow(display,windows->info.id);
03083 (void) FormatMagickString(text,MaxTextExtent," %lux%lu%+ld%+ld",
03084 chop_info.width,chop_info.height,chop_info.x,chop_info.y);
03085 XInfoWidget(display,windows,text);
03086 XHighlightLine(display,windows->image.id,
03087 windows->image.highlight_context,&segment_info);
03088 }
03089 else
03090 if (windows->info.mapped != MagickFalse)
03091 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
03092
03093
03094
03095 XScreenEvent(display,windows,&event);
03096 if (distance > 9)
03097 XHighlightLine(display,windows->image.id,
03098 windows->image.highlight_context,&segment_info);
03099 switch (event.type)
03100 {
03101 case ButtonPress:
03102 {
03103 segment_info.x2=(short int) event.xmotion.x;
03104 segment_info.y2=(short int) event.xmotion.y;
03105 break;
03106 }
03107 case ButtonRelease:
03108 {
03109
03110
03111
03112 segment_info.x2=(short int) event.xbutton.x;
03113 segment_info.y2=(short int) event.xbutton.y;
03114 state|=ExitState;
03115 break;
03116 }
03117 case Expose:
03118 break;
03119 case MotionNotify:
03120 {
03121 segment_info.x2=(short int) event.xmotion.x;
03122 segment_info.y2=(short int) event.xmotion.y;
03123 }
03124 default:
03125 break;
03126 }
03127
03128
03129
03130 if (segment_info.x2 < 0)
03131 segment_info.x2=0;
03132 else
03133 if (segment_info.x2 > windows->image.ximage->width)
03134 segment_info.x2=windows->image.ximage->width;
03135 if (segment_info.y2 < 0)
03136 segment_info.y2=0;
03137 else
03138 if (segment_info.y2 > windows->image.ximage->height)
03139 segment_info.y2=windows->image.ximage->height;
03140 distance=(unsigned int)
03141 (((segment_info.x2-segment_info.x1)*(segment_info.x2-segment_info.x1))+
03142 ((segment_info.y2-segment_info.y1)*(segment_info.y2-segment_info.y1)));
03143
03144
03145
03146 if (direction == HorizontalChopCommand)
03147 {
03148 chop_info.width=(unsigned long) (segment_info.x2-segment_info.x1+1);
03149 chop_info.x=windows->image.x+segment_info.x1;
03150 chop_info.height=0;
03151 chop_info.y=0;
03152 if (segment_info.x1 > (int) segment_info.x2)
03153 {
03154 chop_info.width=(unsigned long) (segment_info.x1-segment_info.x2+1);
03155 chop_info.x=windows->image.x+segment_info.x2;
03156 }
03157 }
03158 else
03159 {
03160 chop_info.width=0;
03161 chop_info.height=(unsigned long) (segment_info.y2-segment_info.y1+1);
03162 chop_info.x=0;
03163 chop_info.y=windows->image.y+segment_info.y1;
03164 if (segment_info.y1 > segment_info.y2)
03165 {
03166 chop_info.height=(unsigned long)
03167 (segment_info.y1-segment_info.y2+1);
03168 chop_info.y=windows->image.y+segment_info.y2;
03169 }
03170 }
03171 } while ((state & ExitState) == 0);
03172 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
03173 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
03174 if (distance <= 9)
03175 return(MagickTrue);
03176
03177
03178
03179 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image);
03180 XSetCursorState(display,windows,MagickTrue);
03181 XCheckRefreshWindows(display,windows);
03182 windows->image.window_changes.width=windows->image.ximage->width-
03183 (unsigned int) chop_info.width;
03184 windows->image.window_changes.height=windows->image.ximage->height-
03185 (unsigned int) chop_info.height;
03186 width=(unsigned int) (*image)->columns;
03187 height=(unsigned int) (*image)->rows;
03188 x=0;
03189 y=0;
03190 if (windows->image.crop_geometry != (char *) NULL)
03191 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
03192 scale_factor=(MagickRealType) width/windows->image.ximage->width;
03193 chop_info.x+=x;
03194 chop_info.x=(int) (scale_factor*chop_info.x+0.5);
03195 chop_info.width=(unsigned int) (scale_factor*chop_info.width+0.5);
03196 scale_factor=(MagickRealType) height/windows->image.ximage->height;
03197 chop_info.y+=y;
03198 chop_info.y=(int) (scale_factor*chop_info.y+0.5);
03199 chop_info.height=(unsigned int) (scale_factor*chop_info.height+0.5);
03200
03201
03202
03203 chop_image=ChopImage(*image,&chop_info,&(*image)->exception);
03204 XSetCursorState(display,windows,MagickFalse);
03205 if (chop_image == (Image *) NULL)
03206 return(MagickFalse);
03207 *image=DestroyImage(*image);
03208 *image=chop_image;
03209
03210
03211
03212 XConfigureImageColormap(display,resource_info,windows,*image);
03213 (void) XConfigureImage(display,resource_info,windows,*image);
03214 return(MagickTrue);
03215 }
03216
03217
03218
03219
03220
03221
03222
03223
03224
03225
03226
03227
03228
03229
03230
03231
03232
03233
03234
03235
03236
03237
03238
03239
03240
03241
03242
03243
03244
03245
03246
03247
03248
03249
03250 static MagickBooleanType XColorEditImage(Display *display,
03251 XResourceInfo *resource_info,XWindows *windows,Image **image)
03252 {
03253 static const char
03254 *ColorEditMenu[] =
03255 {
03256 "Method",
03257 "Pixel Color",
03258 "Border Color",
03259 "Fuzz",
03260 "Undo",
03261 "Help",
03262 "Dismiss",
03263 (char *) NULL
03264 };
03265
03266 static const ModeType
03267 ColorEditCommands[] =
03268 {
03269 ColorEditMethodCommand,
03270 ColorEditColorCommand,
03271 ColorEditBorderCommand,
03272 ColorEditFuzzCommand,
03273 ColorEditUndoCommand,
03274 ColorEditHelpCommand,
03275 ColorEditDismissCommand
03276 };
03277
03278 static PaintMethod
03279 method = PointMethod;
03280
03281 static unsigned int
03282 pen_id = 0;
03283
03284 static XColor
03285 border_color = { 0, 0, 0, 0, 0, 0 };
03286
03287 char
03288 command[MaxTextExtent],
03289 text[MaxTextExtent];
03290
03291 Cursor
03292 cursor;
03293
03294 ExceptionInfo
03295 *exception;
03296
03297 int
03298 entry,
03299 id,
03300 x,
03301 x_offset,
03302 y,
03303 y_offset;
03304
03305 register PixelPacket
03306 *q;
03307
03308 register long
03309 i;
03310
03311 unsigned int
03312 height,
03313 width;
03314
03315 unsigned long
03316 state;
03317
03318 XColor
03319 color;
03320
03321 XEvent
03322 event;
03323
03324
03325
03326
03327 (void) CloneString(&windows->command.name,"Color Edit");
03328 windows->command.data=4;
03329 (void) XCommandWidget(display,windows,ColorEditMenu,(XEvent *) NULL);
03330 (void) XMapRaised(display,windows->command.id);
03331 XClientMessage(display,windows->image.id,windows->im_protocols,
03332 windows->im_update_widget,CurrentTime);
03333
03334
03335
03336 cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap,
03337 resource_info->background_color,resource_info->foreground_color);
03338 (void) XCheckDefineCursor(display,windows->image.id,cursor);
03339
03340
03341
03342 XQueryPosition(display,windows->image.id,&x,&y);
03343 (void) XSelectInput(display,windows->image.id,
03344 windows->image.attributes.event_mask | PointerMotionMask);
03345 state=DefaultState;
03346 do
03347 {
03348 if (windows->info.mapped != MagickFalse)
03349 {
03350
03351
03352
03353 (void) FormatMagickString(text,MaxTextExtent," %+d%+d ",
03354 x+windows->image.x,y+windows->image.y);
03355 XInfoWidget(display,windows,text);
03356 }
03357
03358
03359
03360 XScreenEvent(display,windows,&event);
03361 if (event.xany.window == windows->command.id)
03362 {
03363
03364
03365
03366 id=XCommandWidget(display,windows,ColorEditMenu,&event);
03367 if (id < 0)
03368 {
03369 (void) XCheckDefineCursor(display,windows->image.id,cursor);
03370 continue;
03371 }
03372 switch (ColorEditCommands[id])
03373 {
03374 case ColorEditMethodCommand:
03375 {
03376 char
03377 **methods;
03378
03379
03380
03381
03382 methods=(char **) GetMagickOptions(MagickMethodOptions);
03383 if (methods == (char **) NULL)
03384 break;
03385 entry=XMenuWidget(display,windows,ColorEditMenu[id],
03386 (const char **) methods,command);
03387 if (entry >= 0)
03388 method=(PaintMethod) ParseMagickOption(MagickMethodOptions,
03389 MagickFalse,methods[entry]);
03390 methods=DestroyStringList(methods);
03391 break;
03392 }
03393 case ColorEditColorCommand:
03394 {
03395 const char
03396 *ColorMenu[MaxNumberPens];
03397
03398 int
03399 pen_number;
03400
03401
03402
03403
03404 for (i=0; i < (int) (MaxNumberPens-2); i++)
03405 ColorMenu[i]=resource_info->pen_colors[i];
03406 ColorMenu[MaxNumberPens-2]="Browser...";
03407 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
03408
03409
03410
03411 pen_number=XMenuWidget(display,windows,ColorEditMenu[id],
03412 (const char **) ColorMenu,command);
03413 if (pen_number < 0)
03414 break;
03415 if (pen_number == (MaxNumberPens-2))
03416 {
03417 static char
03418 color_name[MaxTextExtent] = "gray";
03419
03420
03421
03422
03423 resource_info->pen_colors[pen_number]=color_name;
03424 XColorBrowserWidget(display,windows,"Select",color_name);
03425 if (*color_name == '\0')
03426 break;
03427 }
03428
03429
03430
03431 (void) XParseColor(display,windows->map_info->colormap,
03432 resource_info->pen_colors[pen_number],&color);
03433 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
03434 (unsigned int) MaxColors,&color);
03435 windows->pixel_info->pen_colors[pen_number]=color;
03436 pen_id=(unsigned int) pen_number;
03437 break;
03438 }
03439 case ColorEditBorderCommand:
03440 {
03441 const char
03442 *ColorMenu[MaxNumberPens];
03443
03444 int
03445 pen_number;
03446
03447
03448
03449
03450 for (i=0; i < (int) (MaxNumberPens-2); i++)
03451 ColorMenu[i]=resource_info->pen_colors[i];
03452 ColorMenu[MaxNumberPens-2]="Browser...";
03453 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
03454
03455
03456
03457 pen_number=XMenuWidget(display,windows,ColorEditMenu[id],
03458 (const char **) ColorMenu,command);
03459 if (pen_number < 0)
03460 break;
03461 if (pen_number == (MaxNumberPens-2))
03462 {
03463 static char
03464 color_name[MaxTextExtent] = "gray";
03465
03466
03467
03468
03469 resource_info->pen_colors[pen_number]=color_name;
03470 XColorBrowserWidget(display,windows,"Select",color_name);
03471 if (*color_name == '\0')
03472 break;
03473 }
03474
03475
03476
03477 (void) XParseColor(display,windows->map_info->colormap,
03478 resource_info->pen_colors[pen_number],&border_color);
03479 break;
03480 }
03481 case ColorEditFuzzCommand:
03482 {
03483 static char
03484 fuzz[MaxTextExtent];
03485
03486 static const char
03487 *FuzzMenu[] =
03488 {
03489 "0%",
03490 "2%",
03491 "5%",
03492 "10%",
03493 "15%",
03494 "Dialog...",
03495 (char *) NULL,
03496 };
03497
03498
03499
03500
03501 entry=XMenuWidget(display,windows,ColorEditMenu[id],FuzzMenu,
03502 command);
03503 if (entry < 0)
03504 break;
03505 if (entry != 5)
03506 {
03507 (*image)->fuzz=SiPrefixToDouble(FuzzMenu[entry],1.0*
03508 QuantumRange+1.0);
03509 break;
03510 }
03511 (void) (void) CopyMagickString(fuzz,"20%",MaxTextExtent);
03512 (void) XDialogWidget(display,windows,"Ok",
03513 "Enter fuzz factor (0.0 - 99.9%):",fuzz);
03514 if (*fuzz == '\0')
03515 break;
03516 (void) ConcatenateMagickString(fuzz,"%",MaxTextExtent);
03517 (*image)->fuzz=SiPrefixToDouble(fuzz,1.0*QuantumRange+1.0);
03518 break;
03519 }
03520 case ColorEditUndoCommand:
03521 {
03522 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
03523 image);
03524 break;
03525 }
03526 case ColorEditHelpCommand:
03527 default:
03528 {
03529 XTextViewWidget(display,resource_info,windows,MagickFalse,
03530 "Help Viewer - Image Annotation",ImageColorEditHelp);
03531 break;
03532 }
03533 case ColorEditDismissCommand:
03534 {
03535
03536
03537
03538 state|=EscapeState;
03539 state|=ExitState;
03540 break;
03541 }
03542 }
03543 (void) XCheckDefineCursor(display,windows->image.id,cursor);
03544 continue;
03545 }
03546 switch (event.type)
03547 {
03548 case ButtonPress:
03549 {
03550 if (event.xbutton.button != Button1)
03551 break;
03552 if ((event.xbutton.window != windows->image.id) &&
03553 (event.xbutton.window != windows->magnify.id))
03554 break;
03555
03556
03557
03558 x=event.xbutton.x;
03559 y=event.xbutton.y;
03560 (void) XMagickCommand(display,resource_info,windows,
03561 SaveToUndoBufferCommand,image);
03562 state|=UpdateConfigurationState;
03563 break;
03564 }
03565 case ButtonRelease:
03566 {
03567 if (event.xbutton.button != Button1)
03568 break;
03569 if ((event.xbutton.window != windows->image.id) &&
03570 (event.xbutton.window != windows->magnify.id))
03571 break;
03572
03573
03574
03575 x=event.xbutton.x;
03576 y=event.xbutton.y;
03577 XConfigureImageColormap(display,resource_info,windows,*image);
03578 (void) XConfigureImage(display,resource_info,windows,*image);
03579 XInfoWidget(display,windows,text);
03580 (void) XCheckDefineCursor(display,windows->image.id,cursor);
03581 state&=(~UpdateConfigurationState);
03582 break;
03583 }
03584 case Expose:
03585 break;
03586 case KeyPress:
03587 {
03588 KeySym
03589 key_symbol;
03590
03591 if (event.xkey.window == windows->magnify.id)
03592 {
03593 Window
03594 window;
03595
03596 window=windows->magnify.id;
03597 while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ;
03598 }
03599 if (event.xkey.window != windows->image.id)
03600 break;
03601
03602
03603
03604 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
03605 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
03606 switch ((int) key_symbol)
03607 {
03608 case XK_Escape:
03609 case XK_F20:
03610 {
03611
03612
03613
03614 state|=ExitState;
03615 break;
03616 }
03617 case XK_F1:
03618 case XK_Help:
03619 {
03620 XTextViewWidget(display,resource_info,windows,MagickFalse,
03621 "Help Viewer - Image Annotation",ImageColorEditHelp);
03622 break;
03623 }
03624 default:
03625 {
03626 (void) XBell(display,0);
03627 break;
03628 }
03629 }
03630 break;
03631 }
03632 case MotionNotify:
03633 {
03634
03635
03636
03637 x=event.xmotion.x;
03638 y=event.xmotion.y;
03639 if (windows->info.mapped != MagickFalse)
03640 {
03641 if ((x < (int) (windows->info.x+windows->info.width)) &&
03642 (y < (int) (windows->info.y+windows->info.height)))
03643 (void) XWithdrawWindow(display,windows->info.id,
03644 windows->info.screen);
03645 }
03646 else
03647 if ((x > (int) (windows->info.x+windows->info.width)) ||
03648 (y > (int) (windows->info.y+windows->info.height)))
03649 (void) XMapWindow(display,windows->info.id);
03650 break;
03651 }
03652 default:
03653 break;
03654 }
03655 if (event.xany.window == windows->magnify.id)
03656 {
03657 x=windows->magnify.x-windows->image.x;
03658 y=windows->magnify.y-windows->image.y;
03659 }
03660 x_offset=x;
03661 y_offset=y;
03662 if ((state & UpdateConfigurationState) != 0)
03663 {
03664 int
03665 x,
03666 y;
03667
03668
03669
03670
03671 (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1,
03672 MagickTrue);
03673 color=windows->pixel_info->pen_colors[pen_id];
03674 XPutPixel(windows->image.ximage,x_offset,y_offset,color.pixel);
03675 width=(unsigned int) (*image)->columns;
03676 height=(unsigned int) (*image)->rows;
03677 x=0;
03678 y=0;
03679 if (windows->image.crop_geometry != (char *) NULL)
03680 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
03681 &width,&height);
03682 x_offset=(int)
03683 (width*(windows->image.x+x_offset)/windows->image.ximage->width+x);
03684 y_offset=(int)
03685 (height*(windows->image.y+y_offset)/windows->image.ximage->height+y);
03686 if ((x_offset < 0) || (y_offset < 0))
03687 continue;
03688 if ((x_offset >= (long) (*image)->columns) ||
03689 (y_offset >= (long) (*image)->rows))
03690 continue;
03691 exception=(&(*image)->exception);
03692 switch (method)
03693 {
03694 case PointMethod:
03695 default:
03696 {
03697
03698
03699
03700 if (SetImageStorageClass(*image,DirectClass) == MagickFalse)
03701 return(MagickFalse);
03702 q=GetAuthenticPixels(*image,x_offset,y_offset,1,1,exception);
03703 if (q == (PixelPacket *) NULL)
03704 break;
03705 q->red=ScaleShortToQuantum(color.red);
03706 q->green=ScaleShortToQuantum(color.green);
03707 q->blue=ScaleShortToQuantum(color.blue);
03708 (void) SyncAuthenticPixels(*image,&(*image)->exception);
03709 break;
03710 }
03711 case ReplaceMethod:
03712 {
03713 PixelPacket
03714 target;
03715
03716
03717
03718
03719 (void) GetOneVirtualPixel(*image,x_offset,y_offset,&target,
03720 &(*image)->exception);
03721 if ((*image)->storage_class == DirectClass)
03722 {
03723 for (y=0; y < (long) (*image)->rows; y++)
03724 {
03725 q=GetAuthenticPixels(*image,0,y,(*image)->columns,1,
03726 exception);
03727 if (q == (PixelPacket *) NULL)
03728 break;
03729 for (x=0; x < (int) (*image)->columns; x++)
03730 {
03731 if (IsColorSimilar(*image,q,&target))
03732 {
03733 q->red=ScaleShortToQuantum(color.red);
03734 q->green=ScaleShortToQuantum(color.green);
03735 q->blue=ScaleShortToQuantum(color.blue);
03736 }
03737 q++;
03738 }
03739 if (SyncAuthenticPixels(*image,exception) == MagickFalse)
03740 break;
03741 }
03742 }
03743 else
03744 {
03745 for (i=0; i < (int) (*image)->colors; i++)
03746 if (IsColorSimilar(*image,(*image)->colormap+i,&target))
03747 {
03748 (*image)->colormap[i].red=ScaleShortToQuantum(color.red);
03749 (*image)->colormap[i].green=ScaleShortToQuantum(
03750 color.green);
03751 (*image)->colormap[i].blue=ScaleShortToQuantum(
03752 color.blue);
03753 }
03754 (void) SyncImage(*image);
03755 }
03756 break;
03757 }
03758 case FloodfillMethod:
03759 case FillToBorderMethod:
03760 {
03761 DrawInfo
03762 *draw_info;
03763
03764 MagickPixelPacket
03765 target;
03766
03767
03768
03769
03770 (void) GetOneVirtualMagickPixel(*image,x_offset,y_offset,&target,
03771 exception);
03772 if (method == FillToBorderMethod)
03773 {
03774 target.red=(MagickRealType)
03775 ScaleShortToQuantum(border_color.red);
03776 target.green=(MagickRealType)
03777 ScaleShortToQuantum(border_color.green);
03778 target.blue=(MagickRealType)
03779 ScaleShortToQuantum(border_color.blue);
03780 }
03781 draw_info=CloneDrawInfo(resource_info->image_info,
03782 (DrawInfo *) NULL);
03783 (void) QueryColorDatabase(resource_info->pen_colors[pen_id],
03784 &draw_info->fill,exception);
03785 (void) FloodfillPaintImage(*image,DefaultChannels,draw_info,&target,
03786 x_offset,y_offset,method == FloodfillMethod ? MagickFalse :
03787 MagickTrue);
03788 draw_info=DestroyDrawInfo(draw_info);
03789 break;
03790 }
03791 case ResetMethod:
03792 {
03793
03794
03795
03796 if (SetImageStorageClass(*image,DirectClass) == MagickFalse)
03797 return(MagickFalse);
03798 for (y=0; y < (long) (*image)->rows; y++)
03799 {
03800 q=QueueAuthenticPixels(*image,0,y,(*image)->columns,1,exception);
03801 if (q == (PixelPacket *) NULL)
03802 break;
03803 for (x=0; x < (int) (*image)->columns; x++)
03804 {
03805 q->red=ScaleShortToQuantum(color.red);
03806 q->green=ScaleShortToQuantum(color.green);
03807 q->blue=ScaleShortToQuantum(color.blue);
03808 q++;
03809 }
03810 if (SyncAuthenticPixels(*image,exception) == MagickFalse)
03811 break;
03812 }
03813 break;
03814 }
03815 }
03816 state&=(~UpdateConfigurationState);
03817 }
03818 } while ((state & ExitState) == 0);
03819 (void) XSelectInput(display,windows->image.id,
03820 windows->image.attributes.event_mask);
03821 XSetCursorState(display,windows,MagickFalse);
03822 (void) XFreeCursor(display,cursor);
03823 return(MagickTrue);
03824 }
03825
03826
03827
03828
03829
03830
03831
03832
03833
03834
03835
03836
03837
03838
03839
03840
03841
03842
03843
03844
03845
03846
03847
03848
03849
03850
03851
03852
03853
03854
03855
03856
03857
03858 static MagickBooleanType XCompositeImage(Display *display,
03859 XResourceInfo *resource_info,XWindows *windows,Image *image)
03860 {
03861 static char
03862 displacement_geometry[MaxTextExtent] = "30x30",
03863 filename[MaxTextExtent] = "\0";
03864
03865 static const char
03866 *CompositeMenu[] =
03867 {
03868 "Operators",
03869 "Dissolve",
03870 "Displace",
03871 "Help",
03872 "Dismiss",
03873 (char *) NULL
03874 };
03875
03876 static CompositeOperator
03877 compose = CopyCompositeOp;
03878
03879 static const ModeType
03880 CompositeCommands[] =
03881 {
03882 CompositeOperatorsCommand,
03883 CompositeDissolveCommand,
03884 CompositeDisplaceCommand,
03885 CompositeHelpCommand,
03886 CompositeDismissCommand
03887 };
03888
03889 char
03890 text[MaxTextExtent];
03891
03892 Cursor
03893 cursor;
03894
03895 Image
03896 *composite_image;
03897
03898 int
03899 entry,
03900 id,
03901 x,
03902 y;
03903
03904 MagickRealType
03905 blend,
03906 scale_factor;
03907
03908 RectangleInfo
03909 highlight_info,
03910 composite_info;
03911
03912 unsigned int
03913 height,
03914 width;
03915
03916 unsigned long
03917 state;
03918
03919 XEvent
03920 event;
03921
03922
03923
03924
03925 XFileBrowserWidget(display,windows,"Composite",filename);
03926 if (*filename == '\0')
03927 return(MagickTrue);
03928
03929
03930
03931 XSetCursorState(display,windows,MagickTrue);
03932 XCheckRefreshWindows(display,windows);
03933 (void) CopyMagickString(resource_info->image_info->filename,filename,
03934 MaxTextExtent);
03935 composite_image=ReadImage(resource_info->image_info,&image->exception);
03936 CatchException(&image->exception);
03937 XSetCursorState(display,windows,MagickFalse);
03938 if (composite_image == (Image *) NULL)
03939 return(MagickFalse);
03940
03941
03942
03943 (void) CloneString(&windows->command.name,"Composite");
03944 windows->command.data=1;
03945 (void) XCommandWidget(display,windows,CompositeMenu,(XEvent *) NULL);
03946 (void) XMapRaised(display,windows->command.id);
03947 XClientMessage(display,windows->image.id,windows->im_protocols,
03948 windows->im_update_widget,CurrentTime);
03949
03950
03951
03952 XQueryPosition(display,windows->image.id,&x,&y);
03953 (void) XSelectInput(display,windows->image.id,
03954 windows->image.attributes.event_mask | PointerMotionMask);
03955 composite_info.x=windows->image.x+x;
03956 composite_info.y=windows->image.y+y;
03957 composite_info.width=0;
03958 composite_info.height=0;
03959 cursor=XCreateFontCursor(display,XC_ul_angle);
03960 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
03961 blend=0.0;
03962 state=DefaultState;
03963 do
03964 {
03965 if (windows->info.mapped != MagickFalse)
03966 {
03967
03968
03969
03970 (void) FormatMagickString(text,MaxTextExtent," %+ld%+ld ",
03971 composite_info.x,composite_info.y);
03972 XInfoWidget(display,windows,text);
03973 }
03974 highlight_info=composite_info;
03975 highlight_info.x=composite_info.x-windows->image.x;
03976 highlight_info.y=composite_info.y-windows->image.y;
03977 XHighlightRectangle(display,windows->image.id,
03978 windows->image.highlight_context,&highlight_info);
03979
03980
03981
03982 XScreenEvent(display,windows,&event);
03983 XHighlightRectangle(display,windows->image.id,
03984 windows->image.highlight_context,&highlight_info);
03985 if (event.xany.window == windows->command.id)
03986 {
03987
03988
03989
03990 id=XCommandWidget(display,windows,CompositeMenu,&event);
03991 if (id < 0)
03992 continue;
03993 switch (CompositeCommands[id])
03994 {
03995 case CompositeOperatorsCommand:
03996 {
03997 char
03998 command[MaxTextExtent],
03999 **operators;
04000
04001
04002
04003
04004 operators=GetMagickOptions(MagickComposeOptions);
04005 if (operators == (char **) NULL)
04006 break;
04007 entry=XMenuWidget(display,windows,CompositeMenu[id],
04008 (const char **) operators,command);
04009 if (entry >= 0)
04010 compose=(CompositeOperator) ParseMagickOption(
04011 MagickComposeOptions,MagickFalse,operators[entry]);
04012 operators=DestroyStringList(operators);
04013 break;
04014 }
04015 case CompositeDissolveCommand:
04016 {
04017 static char
04018 factor[MaxTextExtent] = "20.0";
04019
04020
04021
04022
04023 (void) XSetFunction(display,windows->image.highlight_context,
04024 GXcopy);
04025 (void) XDialogWidget(display,windows,"Dissolve",
04026 "Enter the blend factor (0.0 - 99.9%):",factor);
04027 (void) XSetFunction(display,windows->image.highlight_context,
04028 GXinvert);
04029 if (*factor == '\0')
04030 break;
04031 blend=StringToDouble(factor);
04032 compose=DissolveCompositeOp;
04033 break;
04034 }
04035 case CompositeDisplaceCommand:
04036 {
04037
04038
04039
04040 (void) XSetFunction(display,windows->image.highlight_context,
04041 GXcopy);
04042 (void) XDialogWidget(display,windows,"Displace",
04043 "Enter the horizontal and vertical scale:",displacement_geometry);
04044 (void) XSetFunction(display,windows->image.highlight_context,
04045 GXinvert);
04046 if (*displacement_geometry == '\0')
04047 break;
04048 compose=DisplaceCompositeOp;
04049 break;
04050 }
04051 case CompositeHelpCommand:
04052 {
04053 (void) XSetFunction(display,windows->image.highlight_context,
04054 GXcopy);
04055 XTextViewWidget(display,resource_info,windows,MagickFalse,
04056 "Help Viewer - Image Composite",ImageCompositeHelp);
04057 (void) XSetFunction(display,windows->image.highlight_context,
04058 GXinvert);
04059 break;
04060 }
04061 case CompositeDismissCommand:
04062 {
04063
04064
04065
04066 state|=EscapeState;
04067 state|=ExitState;
04068 break;
04069 }
04070 default:
04071 break;
04072 }
04073 continue;
04074 }
04075 switch (event.type)
04076 {
04077 case ButtonPress:
04078 {
04079 if (image->debug != MagickFalse)
04080 (void) LogMagickEvent(X11Event,GetMagickModule(),
04081 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
04082 event.xbutton.button,event.xbutton.x,event.xbutton.y);
04083 if (event.xbutton.button != Button1)
04084 break;
04085 if (event.xbutton.window != windows->image.id)
04086 break;
04087
04088
04089
04090 composite_info.width=composite_image->columns;
04091 composite_info.height=composite_image->rows;
04092 (void) XCheckDefineCursor(display,windows->image.id,cursor);
04093 composite_info.x=windows->image.x+event.xbutton.x;
04094 composite_info.y=windows->image.y+event.xbutton.y;
04095 break;
04096 }
04097 case ButtonRelease:
04098 {
04099 if (image->debug != MagickFalse)
04100 (void) LogMagickEvent(X11Event,GetMagickModule(),
04101 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
04102 event.xbutton.button,event.xbutton.x,event.xbutton.y);
04103 if (event.xbutton.button != Button1)
04104 break;
04105 if (event.xbutton.window != windows->image.id)
04106 break;
04107 if ((composite_info.width != 0) && (composite_info.height != 0))
04108 {
04109
04110
04111
04112 composite_info.x=windows->image.x+event.xbutton.x;
04113 composite_info.y=windows->image.y+event.xbutton.y;
04114 state|=ExitState;
04115 }
04116 break;
04117 }
04118 case Expose:
04119 break;
04120 case KeyPress:
04121 {
04122 char
04123 command[MaxTextExtent];
04124
04125 KeySym
04126 key_symbol;
04127
04128 int
04129 length;
04130
04131 if (event.xkey.window != windows->image.id)
04132 break;
04133
04134
04135
04136 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
04137 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
04138 *(command+length)='\0';
04139 if (image->debug != MagickFalse)
04140 (void) LogMagickEvent(X11Event,GetMagickModule(),
04141 "Key press: 0x%lx (%s)",(unsigned long) key_symbol,command);
04142 switch ((int) key_symbol)
04143 {
04144 case XK_Escape:
04145 case XK_F20:
04146 {
04147
04148
04149
04150 composite_image=DestroyImage(composite_image);
04151 state|=EscapeState;
04152 state|=ExitState;
04153 break;
04154 }
04155 case XK_F1:
04156 case XK_Help:
04157 {
04158 (void) XSetFunction(display,windows->image.highlight_context,
04159 GXcopy);
04160 XTextViewWidget(display,resource_info,windows,MagickFalse,
04161 "Help Viewer - Image Composite",ImageCompositeHelp);
04162 (void) XSetFunction(display,windows->image.highlight_context,
04163 GXinvert);
04164 break;
04165 }
04166 default:
04167 {
04168 (void) XBell(display,0);
04169 break;
04170 }
04171 }
04172 break;
04173 }
04174 case MotionNotify:
04175 {
04176
04177
04178
04179 x=event.xmotion.x;
04180 y=event.xmotion.y;
04181 if (windows->info.mapped != MagickFalse)
04182 {
04183 if ((x < (int) (windows->info.x+windows->info.width)) &&
04184 (y < (int) (windows->info.y+windows->info.height)))
04185 (void) XWithdrawWindow(display,windows->info.id,
04186 windows->info.screen);
04187 }
04188 else
04189 if ((x > (int) (windows->info.x+windows->info.width)) ||
04190 (y > (int) (windows->info.y+windows->info.height)))
04191 (void) XMapWindow(display,windows->info.id);
04192 composite_info.x=windows->image.x+x;
04193 composite_info.y=windows->image.y+y;
04194 break;
04195 }
04196 default:
04197 {
04198 if (image->debug != MagickFalse)
04199 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
04200 event.type);
04201 break;
04202 }
04203 }
04204 } while ((state & ExitState) == 0);
04205 (void) XSelectInput(display,windows->image.id,
04206 windows->image.attributes.event_mask);
04207 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
04208 XSetCursorState(display,windows,MagickFalse);
04209 (void) XFreeCursor(display,cursor);
04210 if ((state & EscapeState) != 0)
04211 return(MagickTrue);
04212
04213
04214
04215 XSetCursorState(display,windows,MagickTrue);
04216 XCheckRefreshWindows(display,windows);
04217 width=(unsigned int) image->columns;
04218 height=(unsigned int) image->rows;
04219 x=0;
04220 y=0;
04221 if (windows->image.crop_geometry != (char *) NULL)
04222 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
04223 scale_factor=(MagickRealType) width/windows->image.ximage->width;
04224 composite_info.x+=x;
04225 composite_info.x=(int) (scale_factor*composite_info.x+0.5);
04226 composite_info.width=(unsigned int) (scale_factor*composite_info.width+0.5);
04227 scale_factor=(MagickRealType) height/windows->image.ximage->height;
04228 composite_info.y+=y;
04229 composite_info.y=(int) (scale_factor*composite_info.y+0.5);
04230 composite_info.height=(unsigned int) (scale_factor*composite_info.height+0.5);
04231 if ((composite_info.width != composite_image->columns) ||
04232 (composite_info.height != composite_image->rows))
04233 {
04234 Image
04235 *resize_image;
04236
04237
04238
04239
04240 resize_image=ZoomImage(composite_image,composite_info.width,
04241 composite_info.height,&image->exception);
04242 composite_image=DestroyImage(composite_image);
04243 if (resize_image == (Image *) NULL)
04244 {
04245 XSetCursorState(display,windows,MagickFalse);
04246 return(MagickFalse);
04247 }
04248 composite_image=resize_image;
04249 }
04250 if (compose == DisplaceCompositeOp)
04251 (void) SetImageArtifact(composite_image,"compose:args",
04252 displacement_geometry);
04253 if (blend != 0.0)
04254 {
04255 ExceptionInfo
04256 *exception;
04257
04258 int
04259 y;
04260
04261 Quantum
04262 opacity;
04263
04264 register int
04265 x;
04266
04267 register PixelPacket
04268 *q;
04269
04270
04271
04272
04273 (void) SetImageAlphaChannel(composite_image,OpaqueAlphaChannel);
04274 opacity=(Quantum) (ScaleQuantumToChar((Quantum) QuantumRange)-
04275 ((long) ScaleQuantumToChar((Quantum) QuantumRange)*blend)/100);
04276 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
04277 return(MagickFalse);
04278 image->matte=MagickTrue;
04279 exception=(&image->exception);
04280 for (y=0; y < (long) image->rows; y++)
04281 {
04282 q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
04283 if (q == (PixelPacket *) NULL)
04284 break;
04285 for (x=0; x < (int) image->columns; x++)
04286 {
04287 q->opacity=opacity;
04288 q++;
04289 }
04290 if (SyncAuthenticPixels(image,exception) == MagickFalse)
04291 break;
04292 }
04293 }
04294
04295
04296
04297 (void) CompositeImage(image,compose,composite_image,composite_info.x,
04298 composite_info.y);
04299 composite_image=DestroyImage(composite_image);
04300 XSetCursorState(display,windows,MagickFalse);
04301
04302
04303
04304 XConfigureImageColormap(display,resource_info,windows,image);
04305 (void) XConfigureImage(display,resource_info,windows,image);
04306 return(MagickTrue);
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
04340
04341 static MagickBooleanType XConfigureImage(Display *display,
04342 XResourceInfo *resource_info,XWindows *windows,Image *image)
04343 {
04344 char
04345 geometry[MaxTextExtent];
04346
04347 long
04348 x,
04349 y;
04350
04351 MagickStatusType
04352 status;
04353
04354 unsigned long
04355 mask,
04356 height,
04357 width;
04358
04359 XSizeHints
04360 *size_hints;
04361
04362 XWindowChanges
04363 window_changes;
04364
04365
04366
04367
04368 width=(unsigned int) windows->image.window_changes.width;
04369 height=(unsigned int) windows->image.window_changes.height;
04370 if (image->debug != MagickFalse)
04371 (void) LogMagickEvent(X11Event,GetMagickModule(),
04372 "Configure Image: %dx%d=>%lux%lu",windows->image.ximage->width,
04373 windows->image.ximage->height,width,height);
04374 if ((width*height) == 0)
04375 return(MagickTrue);
04376 x=0;
04377 y=0;
04378
04379
04380
04381 XSetCursorState(display,windows,MagickTrue);
04382 (void) XFlush(display);
04383 if (((int) width != windows->image.ximage->width) ||
04384 ((int) height != windows->image.ximage->height))
04385 image->taint=MagickTrue;
04386 windows->magnify.x=(int)
04387 width*windows->magnify.x/windows->image.ximage->width;
04388 windows->magnify.y=(int)
04389 height*windows->magnify.y/windows->image.ximage->height;
04390 windows->image.x=(int) (width*windows->image.x/windows->image.ximage->width);
04391 windows->image.y=(int)
04392 (height*windows->image.y/windows->image.ximage->height);
04393 status=XMakeImage(display,resource_info,&windows->image,image,
04394 (unsigned int) width,(unsigned int) height);
04395 if (status == MagickFalse)
04396 XNoticeWidget(display,windows,"Unable to configure X image:",
04397 windows->image.name);
04398
04399
04400
04401 if (resource_info->image_geometry != (char *) NULL)
04402 (void) FormatMagickString(geometry,MaxTextExtent,"%s>!",
04403 resource_info->image_geometry);
04404 else
04405 (void) FormatMagickString(geometry,MaxTextExtent,"%ux%u+0+0>!",
04406 XDisplayWidth(display,windows->image.screen),
04407 XDisplayHeight(display,windows->image.screen));
04408 (void) ParseMetaGeometry(geometry,&x,&y,&width,&height);
04409 window_changes.width=(int) width;
04410 if (window_changes.width > XDisplayWidth(display,windows->image.screen))
04411 window_changes.width=XDisplayWidth(display,windows->image.screen);
04412 window_changes.height=(int) height;
04413 if (window_changes.height > XDisplayHeight(display,windows->image.screen))
04414 window_changes.height=XDisplayHeight(display,windows->image.screen);
04415 mask=(unsigned long) (CWWidth | CWHeight);
04416 if (resource_info->backdrop)
04417 {
04418 mask|=CWX | CWY;
04419 window_changes.x=(int)
04420 ((XDisplayWidth(display,windows->image.screen)/2)-(width/2));
04421 window_changes.y=(int)
04422 ((XDisplayHeight(display,windows->image.screen)/2)-(height/2));
04423 }
04424 (void) XReconfigureWMWindow(display,windows->image.id,windows->image.screen,
04425 (unsigned int) mask,&window_changes);
04426 (void) XClearWindow(display,windows->image.id);
04427 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
04428
04429
04430
04431 if (windows->magnify.mapped != MagickFalse)
04432 XMakeMagnifyImage(display,windows);
04433 windows->pan.crop_geometry=windows->image.crop_geometry;
04434 XBestIconSize(display,&windows->pan,image);
04435 while (((windows->pan.width << 1) < MaxIconSize) &&
04436 ((windows->pan.height << 1) < MaxIconSize))
04437 {
04438 windows->pan.width<<=1;
04439 windows->pan.height<<=1;
04440 }
04441 if (windows->pan.geometry != (char *) NULL)
04442 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
04443 &windows->pan.width,&windows->pan.height);
04444 window_changes.width=(int) windows->pan.width;
04445 window_changes.height=(int) windows->pan.