1/* 2 3 ImageMagick operations edited by Alan Gibson (aka "snibgo"; snibgo at earthling dot net). 4 5 1-Apr-2014 6 Minor corrections to Geometry_widget and Alpha. 7 Added loads of widgets and Menuactions. 8 Not fully tested. 9 5-Apr-2014 10 Many more menu actions. 11 Reorganised Magick menu. 12 10-Apr-2014 13 Many more menu actions. 14 11-Apr-2014 jcupitt 15 Split to separate _magick.def 16 Add 0-ary and 2-ary system 17 Put utility funcs into a Magick class 18 11-Apr-2014 snibgo 19 Added VirtualPixelBack for cases where background is only relevant when VP=Background 20 17-Apr-2014 snibgo 21 Many small changes. 22 2-May-2014 jcupitt 23 Added Magick.version 24 30-June-2014 25 Put single-quotes around command exe to help win 26 1-July-2014 27 Automatically fall back to gm if we can't find convert 28 17-July-2014 29 better GM support 30 31 32 Last update: 17-July-2014. 33 34 For details of ImageMagick operations, see http://www.imagemagick.org/script/command-line-options.php etc. 35 36*/ 37 38/* Put these in a class to avoid filling the main namespace with IM stuff. 39 */ 40 41Magick = class { 42 43 // first gm on path, or "" 44 gm_path = search_for "gm"; 45 46 // first convert on $PATH, or "" 47 // we check for the convert we ship first 48 convert_path 49 = vips_convert, vips_convert != "" 50 = search_for "convert" 51 { 52 // the convert we ship with the vips binary on some platforms, or "" 53 vips_convert 54 = search (path_absolute convert) 55 { 56 vipshome = path_parse (expand "$VIPSHOME"); 57 convert = vipshome ++ ["bin", "convert" ++ expand "$EXEEXT"]; 58 } 59 } 60 61 use_gm_pref = Workspaces.Preferences.USE_GRAPHICSMAGICK; 62 63 // Are we in GM or IM mode? 64 use_gm 65 = true, use_gm_pref && gm_path != "" 66 = false, !use_gm_pref && convert_path != "" 67 = false, convert_path != "" 68 = true, gm_path != "" 69 = error "neither IM nor GM executable found"; 70 71 command_path 72 = gm_path, use_gm 73 = convert_path; 74 75 // try to get the version as eg. [6, 7, 7, 10] 76 // GM versions are smaller, typically [1, 3, 18] 77 version 78 = map parse_int (split (member ".-") version_string) 79 { 80 [output] = vips_call "system" 81 ["'" ++ command_path ++ "' -version"] [$log=>true]; 82 version_string 83 = (split (equal ' ') output)?1, use_gm 84 = (split (equal ' ') output)?2; 85 } 86 87 // make a command-line ... args is a [str] we join with spaces 88 command args 89 = "'" ++ command_path ++ "' " ++ join_sep " " args' 90 { 91 args' 92 = ["convert"] ++ args, use_gm 93 = args; 94 } 95 96 // capabilities ... different versions support different features, we 97 // turn features on and off based on these 98 99 // would probably be better to test for caps somehow 100 has_intensity 101 = false, use_gm 102 = version?0 > 6 || version?1 > 7; 103 has_channel 104 = false, use_gm 105 = version?0 > 6 || version?1 > 7; 106 107 system0 cmd = system_image0 cmd; 108 system cmd x = map_unary (system_image cmd) x; 109 system2 cmd x y = map_binary (system_image2 cmd) x y; 110 system3 cmd x y z = map_trinary (system_image3 cmd) x y z; 111 112 radius_widget = Scale "Radius" 0 100 10; 113 sigma_widget = Scale "Sigma" 0.1 10 1; 114 angle_widget = Scale "Angle (degrees)" (-360) 360 0; 115 text_widget = String "Text to draw" "AaBbCcDdEe"; 116 117 gamma_widget = Scale "Gamma" 0 10 1; 118 colors_widget = Scale "Colors" 1 10 3; 119 resize_widget = Scale "Resize (percent)" 0 500 100; 120 fuzz_widget = Scale "Fuzz (percent)" 0 100 0; 121 blur_rad_widget = Scale "Radius (0=auto)" 0 100 0; 122 123 // a colour with no enclosing quotes ... use this if we know there are 124 // some quotes at an outer level 125 print_colour_nq triple 126 = concat ["#", concat (map fmt triple)] 127 { 128 fmt x = reverse (take 2 (reverse (print_base 16 (x + 256)))); 129 } 130 131 // we need the quotes because # is the comment character in *nix 132 print_colour triple = "\"" ++ print_colour_nq triple ++ "\""; 133 134 Foreground triple = class 135 Colour "sRGB" triple { 136 137 _flag = "-fill " ++ print_colour triple; 138 139 Colour_edit space triple = this.Foreground triple; 140 } 141 foreground_widget = Foreground [0, 0, 0]; 142 143 GeneralCol triple = class 144 Colour "sRGB" triple { 145 146 _flag = print_colour_nq triple; 147 148 Colour_edit space triple = this.GeneralCol triple; 149 } 150 generalcol_widget = GeneralCol [0, 0, 0]; 151 152 Background triple = class 153 Colour "sRGB" triple { 154 155 isNone = Toggle "None (transparent black)" false; 156 157 _flag = "-background " ++ if isNone then "None" else print_colour triple; 158 159 Colour_edit space triple = this.Background triple; 160 } 161 background_widget = Background [255, 255, 255]; 162 163 Bordercol triple = class 164 Colour "sRGB" triple { 165 166 _flag = "-bordercolor " ++ print_colour triple; 167 168 Colour_edit space triple = this.Bordercol triple; 169 } 170 bordercol_widget = Bordercol [0, 0, 0]; 171 172 Mattecol triple = class 173 Colour "sRGB" triple { 174 175 _flag = "-mattecolor " ++ print_colour triple; 176 177 Colour_edit space triple = this.Mattecol triple; 178 } 179 mattecol_widget = Mattecol [189, 189, 189]; 180 181 // FIXME: Undercolour, like many others, can have alpha channel. 182 // How does user input this? With a slider? 183 Undercol triple = class 184 Colour "sRGB" triple { 185 186 isNone = Toggle "None (transparent black)" true; 187 188 _flag = if isNone then "" else ("-undercolor " ++ print_colour triple); 189 190 Colour_edit space triple = this.Undercol triple; 191 } 192 undercol_widget = Undercol [0, 0, 0]; 193 194 changeCol_widget = class { 195 _vislevel = 3; 196 197 colour = GeneralCol [0, 0, 0]; 198 fuzz = fuzz_widget; 199 nonMatch = Toggle "change non-matching colours" false; 200 } 201 202 Alpha alpha = class 203 Option_string "Alpha" [ 204 "On", 205 "Off", 206 "Set", 207 "Opaque", 208 "Transparent", 209 "Extract", 210 "Copy", 211 "Shape", 212 "Remove", 213 "Background" 214 ] alpha { 215 216 _flag = "-alpha " ++ alpha; 217 218 Option_edit caption labels value = this.Alpha labels?value; 219 } 220 alpha_widget = Alpha "On"; 221 222 Antialias value = class 223 Toggle "Antialias" value { 224 225 _flag 226 = "-antialias", value 227 = "+antialias"; 228 229 Toggle_edit caption value = this.Antialias value; 230 } 231 antialias_widget = Antialias true; 232 233 Builtin builtin = class 234 Option_string "Builtin" [ 235 // See http://www.imagemagick.org/script/formats.php 236 "rose:", 237 "logo:", 238 "wizard:", 239 "granite:", 240 "netscape:" 241 ] builtin { 242 243 _flag = builtin; 244 245 Option_edit caption labels value = this.Builtin labels?value; 246 } 247 builtin_widget = Builtin "rose:"; 248 249 250 channels_widget = class { 251 // FIXME? Can we grey-out alpha when we have no alpha channel, 252 // show CMY(K) instead of RGB(K) etc? 253 // Yes, perhaps we can create different widgets for RGB, RGBA, CMY, CMYK, CMYA, CMYKA. 254 ChanR valueR = class 255 Toggle "Red" valueR { 256 257 _flag 258 = "R", valueR 259 = ""; 260 261 Toggle_edit caption valueR = this.ChanR valueR; 262 } 263 channelR = ChanR true; 264 265 ChanG valueG = class 266 Toggle "Green" valueG { 267 268 _flag 269 = "G", valueG 270 = ""; 271 272 Toggle_edit caption valueG = this.ChanG valueG; 273 } 274 channelG = ChanG true; 275 276 ChanB valueB = class 277 Toggle "Blue" valueB { 278 279 _flag 280 = "B", valueB 281 = ""; 282 283 Toggle_edit caption valueB = this.ChanB valueB; 284 } 285 channelB = ChanB true; 286 287 ChanK valueK = class 288 Toggle "Black" valueK { 289 290 _flag 291 = "K", valueK 292 = ""; 293 294 Toggle_edit caption valueK = this.ChanK valueK; 295 } 296 channelK = ChanK true; 297 298 ChanA valueA = class 299 Toggle "Alpha" valueA { 300 301 _flag 302 = "A", valueA 303 = ""; 304 305 Toggle_edit caption valueA = this.ChanA valueA; 306 } 307 channelA = ChanA false; 308 309 ChanSy valueSy = class 310 Toggle "Sync" valueSy { 311 312 _flag 313 = ",sync", valueSy 314 = ""; 315 316 Toggle_edit caption valueSy = this.ChanSy valueSy; 317 } 318 channelSy = ChanSy true; 319 320 _rgbka = concat [channelR._flag, 321 channelG._flag, 322 channelB._flag, 323 channelK._flag, 324 channelA._flag 325 ]; 326 327 _flag 328 = "", _rgbka == "" || !has_channel 329 = concat [ "-channel ", 330 _rgbka, 331 channelSy._flag 332 ]; 333 } 334 335 ch_widget = channels_widget; 336 337 Colorspace colsp = class 338 Option_string "Colorspace" [ 339 "CIELab", 340 "CMY", 341 "CMYK", 342 "Gray", 343 "HCL", 344 "HCLp", 345 "HSB", 346 "HSI", 347 "HSL", 348 "HSV", 349 "HWB", 350 "Lab", 351 "LCH", 352 "LCHab", 353 "LCHuv", 354 "LMS", 355 "Log", 356 "Luv", 357 "OHTA", 358 "Rec601Luma", 359 "Rec601YCbCr", 360 "Rec709Luma", 361 "Rec709YCbCr", 362 "RGB", 363 "scRGB", 364 "sRGB", 365 "Transparent", 366 "XYZ", 367 "YCbCr", 368 "YDbDr", 369 "YCC", 370 "YIQ", 371 "YPbPr", 372 "YUV" 373 ] colsp { 374 375 _flag = colsp; 376 377 Option_edit caption labels value = this.Colorspace labels?value; 378 } 379 colorspace_widget = Colorspace "sRGB"; 380 381 Compose comp = class 382 Option_string "Compose method" [ 383 "Atop", 384 "Blend", 385 "Blur", 386 "Bumpmap", 387 "ChangeMask", 388 "Clear", 389 "ColorBurn", 390 "ColorDodge", 391 "Colorize", 392 "CopyBlack", 393 "CopyBlue", 394 "CopyCyan", 395 "CopyGreen", 396 "Copy", 397 "CopyMagenta", 398 "CopyOpacity", 399 "CopyRed", 400 "CopyYellow", 401 "Darken", 402 "DarkenIntensity", 403 "DivideDst", 404 "DivideSrc", 405 "Dst", 406 "Difference", 407 "Displace", 408 "Dissolve", 409 "Distort", 410 "DstAtop", 411 "DstIn", 412 "DstOut", 413 "DstOver", 414 "Exclusion", 415 "HardLight", 416 "Hue", 417 "In", 418 "Lighten", 419 "LightenIntensity", 420 "LinearBurn", 421 "LinearDodge", 422 "LinearLight", 423 "Luminize", 424 "Mathematics", 425 "MinusDst", 426 "MinusSrc", 427 "Modulate", 428 "ModulusAdd", 429 "ModulusSubtract", 430 "Multiply", 431 "None", 432 "Out", 433 "Overlay", 434 "Over", 435 "PegtopLight", 436 "PinLight", 437 "Plus", 438 "Replace", 439 "Saturate", 440 "Screen", 441 "SoftLight", 442 "Src", 443 "SrcAtop", 444 "SrcIn", 445 "SrcOut", 446 "SrcOver", 447 "VividLight", 448 "Xor" 449 ] comp { 450 451 _flag = "-compose " ++ comp; 452 453 Option_edit caption labels value = this.Compose labels?value; 454 } 455 compose_widget = Compose "Over"; 456 // FIXME: Some compose mehods (Displace, Distort, Mathematics) need a string. 457 458 // FIXME: we could use a class that does both -compose and -intensity, for methods LightenIntensity, DarkenIntensity, CopyOpacity, CopyBlack 459 460 coordinate_widget = class { 461 _vislevel = 3; 462 463 x = Expression "X" 0; 464 y = Expression "Y" 0; 465 466 _flag = concat [print x.expr, ",", print y.expr]; 467 }; 468 469 Distort distort = class 470 Option_string "Distort" [ 471 "Affine", 472 "AffineProjection", 473 "ScaleRotateTranslate", 474 "SRT", 475 "Perspective", 476 "PerspectiveProjection", 477 "BilinearForward", 478 "BilinearReverse", 479 "Polynomial", 480 "Arc", 481 "Polar", 482 "DePolar", 483 "Barrel", 484 "BarrelInverse", 485 "Shepards", 486 "Resize" 487 ] distort { 488 489 _flag = distort; 490 491 Option_edit caption labels value = this.Distort labels?value; 492 } 493 distort_widget = Distort "SRT"; 494 495 Dither dither = class 496 Option_string "Dither" [ 497 "None", 498 "FloydSteinberg", 499 "Riemersma" 500 ] dither { 501 502 _flag = "-dither " ++ dither; 503 504 Option_edit caption labels value = this.Dither labels?value; 505 } 506 dither_widget = Dither "FloydSteinberg"; 507 508 Evaluate eval = class 509 Option_string "Evaluate operation" [ 510 "Abs", 511 "Add", 512 "AddModulus", 513 "And", 514 "Cos", 515 "Cosine", 516 "Divide", 517 "Exp", 518 "Exponential", 519 "GaussianNoise", 520 "ImpulseNoise", 521 "LaplacianNoise", 522 "LeftShift", 523 "Log", 524 "Max", 525 "Mean", 526 "Median", 527 "Min", 528 "MultiplicativeNoise", 529 "Multiply", 530 "Or", 531 "PoissonNoise", 532 "Pow", 533 "RightShift", 534 "Set", 535 "Sin", 536 "Sine", 537 "Subtract", 538 "Sum", 539 "Threshold", 540 "ThresholdBlack", 541 "ThresholdWhite", 542 "UniformNoise", 543 "Xor" 544 ] eval { 545 546 _flag = "-evaluate " ++ eval; 547 548 Option_edit caption labels value = this.Evaluate labels?value; 549 } 550 evaluate_widget = Evaluate "Add"; 551 552 Filter filt = class 553 Option_string "Filter" [ 554 "default", 555 "Bartlett", 556 "Blackman", 557 "Bohman", 558 "Box", 559 "Catrom", 560 "Cosine", 561 "Cubic", 562 "Gaussian", 563 "Hamming", 564 "Hann", 565 "Hermite", 566 "Jinc", 567 "Kaiser", 568 "Lagrange", 569 "Lanczos", 570 "Lanczos2", 571 "Lanczos2Sharp", 572 "LanczosRadius", 573 "LanczosSharp", 574 "Mitchell", 575 "Parzen", 576 "Point", 577 "Quadratic", 578 "Robidoux", 579 "RobidouxSharp", 580 "Sinc", 581 "SincFast", 582 "Spline", 583 "Triangle", 584 "Welch" 585 ] filt { 586 587 _flag = if filt == "default" then "" else "-filter " ++ filt; 588 589 Option_edit caption labels value = this.Filter labels?value; 590 } 591 filter_widget = Filter "default"; 592 593 Function func = class 594 Option_string "Function" [ 595 "Polynomial", 596 "Sinusoid", 597 "Arcsin", 598 "Arctan" 599 ] func { 600 601 _flag = func; 602 603 Option_edit caption labels value = this.Function labels?value; 604 } 605 function_widget = Function "Polynomial"; 606 607// "Polynomial (a[n], a[n-1], ... a[1], a[0])", 608// "Sinusoid (freq, phase, amp, bias)", 609// "Arcsin (width, centre, range, bias)", 610// "Arctan (slope, centre, range, bias)" 611 612 Gravity gravity = class 613 Option_string "Gravity" [ 614 "None", 615 "Center", 616 "East", 617 "Forget", 618 "NorthEast", 619 "North", 620 "NorthWest", 621 "SouthEast", 622 "South", 623 "SouthWest", 624 "West", 625 "Static" 626 ] gravity { 627 628 _flag = "-gravity " ++ gravity; 629 630 Option_edit caption labels value = this.Gravity labels?value; 631 } 632 gravity_widget = Gravity "Center"; 633 634 ImageType imagetype = class 635 Option_string "Image type" [ 636 "Bilevel", 637 "ColorSeparation", 638 "ColorSeparationAlpha", 639 "ColorSeparationMatte", 640 "Grayscale", 641 "GrayscaleAlpha", 642 "GrayscaleMatte", 643 "Optimize", 644 "Palette", 645 "PaletteBilevelAlpha", 646 "PaletteBilevelMatte", 647 "PaletteAlpha", 648 "PaletteMatte", 649 "TrueColorAlpha", 650 "TrueColorMatte", 651 "TrueColor" 652 ] imagetype { 653 654 _flag = "-type " ++ imagetype; 655 656 Option_edit caption labels value = this.ImageType labels?value; 657 } 658 imagetype_widget = ImageType "TrueColor"; 659 660 Intensity intensity = class 661 Option_string "Intensity (gray conversion)" [ 662 "Average", 663 "Brightness", 664 "Lightness", 665 "MS", 666 "Rec601Luma", 667 "Rec601Luminance", 668 "Rec709Luma", 669 "Rec709Luminance", 670 "RMS" 671 ] intensity { 672 673 _flag 674 = "-intensity " ++ intensity, has_intensity 675 = ""; 676 677 Option_edit caption labels value = this.Intensity labels?value; 678 } 679 intensity_widget = Intensity "Rec709Luminance"; 680 681 Interpolate interp = class 682 Option_string "Interpolate" [ 683 "default", 684 "Average", 685 "Average4", 686 "Average9", 687 "Average16", 688 "Background", 689 "Bilinear", 690 "Blend", 691 "Integer", 692 "Mesh", 693 "Nearest", 694 "NearestNeighbor", 695 "Spline" 696 ] interp { 697 698 _flag = if interp == "default" then "" else "-interpolate " ++ interp; 699 700 Option_edit caption labels value = this.Interpolate labels?value; 701 } 702 interpolate_widget = Interpolate "default"; 703 704 Kernel kernel = class 705 Option_string "Kernel" [ 706 "Unity", 707 "Gaussian", 708 "DoG", 709 "LoG", 710 "Blur", 711 "Comet", 712 "Binomial", 713 "Laplacian", 714 "Sobel", 715 "FreiChen", 716 "Roberts", 717 "Prewitt", 718 "Compass", 719 "Kirsch", 720 "Diamond", 721 "Square", 722 "Rectangle", 723 "Disk", 724 "Octagon", 725 "Plus", 726 "Cross", 727 "Ring", 728 "Peaks", 729 "Edges", 730 "Corners", 731 "Diagonals", 732 "LineEnds", 733 "LineJunctions", 734 "Ridges", 735 "ConvexHull", 736 "ThinSe", 737 "Skeleton", 738 "Chebyshev", 739 "Manhattan", 740 "Octagonal", 741 "Euclidean" 742 // FIXME: custom kernel 743 ] kernel { 744 745 _flag = kernel; 746 747 Option_edit caption labels value = this.Kernel labels?value; 748 } 749 kernel_widget = Kernel "Unity"; 750 751 ModColSp msp = class 752 Option_string "modulate colorspace" [ 753 "HCL", 754 "HCLp", 755 "HSB", 756 "HSI", 757 "HSL", 758 "HSV", 759 "HWB", 760 "LCH" 761 ] msp { 762 763 _flag = "-set option:modulate:colorspace " ++ msp; 764 765 Option_edit caption labels value = this.ModColSp labels?value; 766 } 767 ModColSp_widget = ModColSp "HSL"; 768 769 MorphMeth morph = class 770 Option_string "Method" [ 771 "Correlate", 772 "Convolve", 773 "Dilate", 774 "Erode", 775 "Close", 776 "Open", 777 "DilateIntensity", 778 "ErodeIntensity", 779 "CloseIntensity", 780 "OpenIntensity", 781 "Smooth", 782 "EdgeOut", 783 "EdgeIn", 784 "Edge", 785 "TopHat", 786 "BottomHat", 787 "HitAndMiss", 788 "Thinning", 789 "Thicken", 790 "Distance", 791 "IterativeDistance" 792 ] morph { 793 794 _flag = morph; 795 796 Option_edit caption labels value = this.MorphMeth labels?value; 797 } 798 morphmeth_widget = MorphMeth "Dilate"; 799 800 Noise noise = class 801 Option_string "Noise" [ 802 "Gaussian", 803 "Impulse", 804 "Laplacian", 805 "Multiplicative", 806 "Poisson", 807 "Random", 808 "Uniform" 809 ] noise { 810 811 _flag = "+noise " ++ noise; 812 813 Option_edit caption labels value = this.Noise labels?value; 814 } 815 noise_widget = Noise "Gaussian"; 816 817 Pattern pattern = class 818 Option_string "Noise" [ 819 // See http://www.imagemagick.org/script/formats.php 820 "bricks", 821 "checkerboard", 822 "circles", 823 "crosshatch", 824 "crosshatch30", 825 "crosshatch45", 826 "gray0", 827 "gray5", 828 "gray10", 829 "gray15", 830 "gray20", 831 "gray25", 832 "gray30", 833 "gray35", 834 "gray40", 835 "gray45", 836 "gray50", 837 "gray55", 838 "gray60", 839 "gray65", 840 "gray70", 841 "gray75", 842 "gray80", 843 "gray85", 844 "gray90", 845 "gray95", 846 "gray100", 847 "hexagons", 848 "horizontal", 849 "horizontal2", 850 "horizontal3", 851 "horizontalsaw", 852 "hs_bdiagonal", 853 "hs_cross", 854 "hs_diagcross", 855 "hs_fdiagonal", 856 "hs_horizontal", 857 "hs_vertical", 858 "left30", 859 "left45", 860 "leftshingle", 861 "octagons", 862 "right30", 863 "right45", 864 "rightshingle", 865 "smallfishscales", 866 "vertical", 867 "vertical2", 868 "vertical3", 869 "verticalbricks", 870 "verticalleftshingle", 871 "verticalrightshingle", 872 "verticalsaw" 873 ] pattern { 874 875 _flag = "pattern:" ++ pattern; 876 877 Option_edit caption labels value = this.Pattern labels?value; 878 } 879 pattern_widget = Pattern "bricks"; 880 881 ResizeType resizet = class 882 Option_string "Resize type" [ 883 "resize", 884 "scale", 885 "sample", 886 "adaptive-resize" 887 ] resizet { 888 889 _flag = resizet; 890 891 Option_edit caption labels value = this.ResizeType labels?value; 892 } 893 ResizeType_widget = ResizeType "resize"; 894 895 Size_widget = class { 896 _vislevel = 3; 897 898 width = Expression "Width (pixels)" 64; 899 height = Expression "Height (pixels)" 64; 900 901 _flag = "-size " ++ 902 print width.expr ++ "x" ++ print height.expr; 903 904 }; 905 906 StatType statt = class 907 Option_string "Statistic type" [ 908 "Gradient", 909 "Maximum", 910 "Mean", 911 "Median", 912 "Minimum", 913 "Mode", 914 "Nonpeak", 915 "StandardDeviation" 916 ] statt { 917 918 _flag = statt; 919 920 Option_edit caption labels value = this.StatType labels?value; 921 } 922 StatType_widget = StatType "Mean"; 923 924 VirtualPixel vp = class 925 Option_string "Virtual pixel" [ 926 "Background", 927 "Black", 928 "CheckerTile", 929 "Dither", 930 "Edge", 931 "Gray", 932 "HorizontalTile", 933 "HorizontalTileEdge", 934 "Mirror", 935 "None", 936 "Random", 937 "Tile", 938 "Transparent", 939 "VerticalTile", 940 "VerticalTileEdge", 941 "White" 942 ] vp { 943 944 _flag = "-virtual-pixel " ++ vp; 945 946 _isBackground = (vp == "Background"); 947 948 Option_edit caption labels value = this.VirtualPixel labels?value; 949 } 950 VirtualPixel_widget = VirtualPixel "Edge"; 951 952 VirtualPixelBack_widget = class { 953 virtpix = Magick.VirtualPixel_widget; 954 background = Magick.background_widget; 955 _flag = (if virtpix._isBackground then (background._flag ++ " ") else "") 956 ++ virtpix._flag; 957 } 958 959 Geometry_widget = class { 960 _vislevel = 3; 961 962 x = Expression "X" 0; 963 y = Expression "Y" 0; 964 hoffset = Expression "Horizontal offset" 0; 965 voffset = Expression "Vertical offset" 0; 966 967 _flag 968 = concat [print x.expr, "x", print y.expr, 969 format hoffset, format voffset] 970 { 971 // print an offset ... we want '+' in front of +ve strings 972 format offset 973 = concat ["+", print offset.expr], offset.expr >= 0 974 = print offset.expr; 975 } 976 }; 977 978 AnnotGeometry_widget = class { 979 _vislevel = 3; 980 981 shearX = Expression "shear X (degrees)" 0; 982 shearY = Expression "shear Y (degrees)" 0; 983 hoffset = Expression "Horizontal offset" 0; 984 voffset = Expression "Vertical offset" 0; 985 986 _flag 987 = concat [print shearX.expr, "x", print shearY.expr, 988 format hoffset, format voffset] 989 { 990 // print an offset ... we want '+' in front of +ve strings 991 format offset 992 = concat ["+", print offset.expr], offset.expr >= 0 993 = print offset.expr; 994 } 995 }; 996 997 OffsetGeometry_widget = class { 998 _vislevel = 3; 999 1000 hoffset = Expression "Horizontal offset" 0; 1001 voffset = Expression "Vertical offset" 0; 1002 1003 _flag = concat [format hoffset, format voffset] 1004 { 1005 // print an offset ... we want '+' in front of +ve strings 1006 format offset 1007 = concat ["+", print offset.expr], offset.expr >= 0 1008 = print offset.expr; 1009 } 1010 }; 1011 1012 WhxyGeometry_widget = class { 1013 _vislevel = 3; 1014 1015 x = Expression "Width" 0; 1016 y = Expression "Height" 0; 1017 hoffset = Expression "Horizontal offset" 0; 1018 voffset = Expression "Vertical offset" 0; 1019 1020 _flag 1021 = concat [print x.expr, "x", print y.expr, 1022 format hoffset, format voffset] 1023 { 1024 // print an offset ... we want '+' in front of +ve strings 1025 format offset 1026 = concat ["+", print offset.expr], offset.expr >= 0 1027 = print offset.expr; 1028 } 1029 }; 1030 1031 FrameGeometry_widget = class { 1032 _vislevel = 3; 1033 1034 x = Expression "Width" 0; 1035 y = Expression "Height" 0; 1036 outbev = Expression "Outer bevel thickness" 0; 1037 inbev = Expression "Inner bevel thickness" 0; 1038 1039 _flag 1040 = concat [print x.expr, "x", print y.expr, 1041 format outbev, format inbev] 1042 { 1043 // print an offset ... we want '+' in front of +ve strings 1044 format offset 1045 = concat ["+", print offset.expr], offset.expr >= 0 1046 = print offset.expr; 1047 } 1048 }; 1049 1050 Font_widget = class { 1051 _vislevel = 3; 1052 1053 family = Option_string "Family" [ 1054 "Arial", 1055 "ArialBlack", 1056 "AvantGarde", 1057 "BitstreamCharter", 1058 "Bookman", 1059 "CenturySchoolbook", 1060 "ComicSansMS", 1061 "Courier", 1062 "CourierNew", 1063 "DejaVuSans", 1064 "DejaVuSansMono", 1065 "DejaVuSerif", 1066 "Dingbats", 1067 "FreeMono", 1068 "FreeSans", 1069 "FreeSerif", 1070 "Garuda", 1071 "Georgia", 1072 "Helvetica", 1073 "HelveticaNarrow", 1074 "Impact", 1075 "LiberationMono", 1076 "LiberationSans", 1077 "LiberationSerif", 1078 "NewCenturySchlbk", 1079 "Palatino", 1080 "Purisa", 1081 "Symbol", 1082 "Times", 1083 "TimesNewRoman", 1084 "Ubuntu", 1085 "Verdana", 1086 "Webdings" 1087 ] "Arial"; 1088 style = Option_string "Style" [ 1089 "Any", "Italic", "Normal", "Oblique" 1090 ] "Normal"; 1091 weight = Scale "Weight" 1 800 400; 1092 size = Scale "Point size" 1 100 12; 1093 stretch = Option_string "Stretch" [ 1094 "Any", "Condensed", "Expanded", "ExtraCondensed", "ExtraExpanded", 1095 "Normal", "SemiCondensed", "SemiExpanded", "UltraCondensed", 1096 "UltraExpanded" 1097 ] "Normal"; 1098 1099 _flag = join_sep " " [ 1100 "-family", family.item, 1101 "-weight", print weight.value, 1102 "-pointsize", print size.value, 1103 "-style", style.item, 1104 "-stretch", stretch.item]; 1105 } 1106} 1107 1108