{"id":7386,"date":"2020-05-05T21:08:45","date_gmt":"2020-05-05T21:08:45","guid":{"rendered":"https:\/\/mehdisalimi.ir\/?p=7386"},"modified":"2020-05-05T21:08:45","modified_gmt":"2020-05-05T21:08:45","slug":"%d8%a8%d9%87-%d8%b1%d9%88%d8%a7%db%8c%d8%aa-%da%a9%d8%af-8","status":"publish","type":"post","link":"https:\/\/mehdisalimi.ir\/?p=7386","title":{"rendered":"[\u0628\u0647 \u0631\u0648\u0627\u06cc\u062a \u06a9\u062f] = [\u0633\u0648\u0631\u0633 \u06a9\u062f \u0646\u0633\u062e\u0647 \u0646\u062e\u0633\u062a \u0641\u062a\u0648\u0634\u0627\u067e &#8211; \u06f1\u06f9\u06f9\u06f0]"},"content":{"rendered":"<p style=\"text-align: justify;\"><span style=\"font-size: 16px;\">\u0647\u0646\u06af\u0627\u0645\u06cc \u06a9\u0647 \u0628\u0631\u0627\u062f\u0631\u0627\u0646 Knoll \u0637\u0631\u0627\u062d\u06cc \u0648 \u0646\u0648\u0634\u062a\u0646 \u06cc\u06a9 \u0628\u0631\u0646\u0627\u0645\u0647\u200c\u200c\u0654 \u0648\u06cc\u0631\u0627\u06cc\u0634 \u062a\u0635\u0648\u06cc\u0631 \u0631\u0627 \u062f\u0631 \u0627\u0648\u0627\u062e\u0631 \u062f\u0647\u0647\u0654 \u06f1\u06f9\u06f8\u06f0 \u0622\u063a\u0627\u0632 \u06a9\u0631\u062f\u0646\u062f\u060c \u062d\u062a\u06cc \u062a\u0635\u0648\u0631\u0634 \u0631\u0627 \u0647\u0645 \u0646\u0645\u06cc\u200c\u06a9\u0631\u062f\u0646\u062f \u06a9\u0647 \u0628\u0627 \u0627\u06cc\u0646 \u06a9\u0627\u0631\u060c \u0648\u0627\u0698\u0647\u200c\u0654 \u062c\u062f\u06cc\u062f\u06cc (\u0641\u062a\u0648\u0634\u0627\u067e) \u0631\u0627 \u0628\u0647 \u0648\u0627\u0698\u06af\u0627\u0646 \u06a9\u0627\u0631\u0628\u0631\u062f\u06cc \u0635\u0646\u0627\u06cc\u0639 \u0637\u0631\u0627\u062d\u06cc\u060c \u0645\u064f\u062f\u060c \u0628\u0633\u062a\u0647\u200c\u0628\u0646\u062f\u06cc \u0648 \u062d\u062a\u06cc \u0633\u06cc\u0646\u0645\u0627 \u0627\u0636\u0627\u0641\u0647 \u062e\u0648\u0627\u0647\u0646\u062f \u06a9\u0631\u062f!<\/span><br \/>\n<span style=\"font-size: 16px;\">Thomas Knoll \u062f\u0631 \u0633\u0627\u0644 \u06f1\u06f9\u06f8\u06f7 \u0647\u0646\u06af\u0627\u0645\u06cc \u06a9\u0647 \u062f\u0631 \u062f\u0627\u0646\u0634\u06af\u0627\u0647 \u0645\u06cc\u0634\u06cc\u06af\u0627\u0646 \u062f\u0627\u0646\u0634\u062c\u0648\u06cc \u062f\u06a9\u062a\u0631\u06cc \u0628\u06cc\u0646\u0627\u06cc\u06cc \u06a9\u0627\u0645\u067e\u06cc\u0648\u062a\u0631\u06cc (Computer Vision) \u0628\u0648\u062f\u060c \u0628\u0631\u0646\u0627\u0645\u0647\u200c\u0627\u06cc \u0631\u0627 \u0628\u0631\u0627\u06cc \u0648\u06cc\u0631\u0627\u06cc\u0634 \u062f\u06cc\u062c\u06cc\u062a\u0627\u0644 \u062a\u0635\u0627\u0648\u06cc\u0631 \u0646\u0648\u0634\u062a. \u0628\u0631\u0627\u062f\u0631\u0634\u060c John Knoll\u060c \u06a9\u0647 \u062f\u0631 \u0622\u0646 \u0632\u0645\u0627\u0646 \u062f\u0631 \u0634\u0631\u06a9\u062a \u062c\u0644\u0648\u0647\u200c\u0647\u0627\u06cc \u0628\u0635\u0631\u06cc Light &amp; Magic \u0645\u0634\u063a\u0648\u0644 \u0628\u0647 \u06a9\u0627\u0631 \u0628\u0648\u062f\u060c \u062f\u0631\u06cc\u0627\u0641\u062a\u0647 \u0628\u0648\u062f \u06a9\u0647 \u0627\u06cc\u0646 \u0628\u0631\u0646\u0627\u0645\u0647 \u0645\u06cc\u200c\u062a\u0648\u0627\u0646\u062f \u062f\u0631 \u0648\u06cc\u0631\u0627\u06cc\u0634 \u062a\u0635\u0627\u0648\u06cc\u0631 \u0645\u0641\u06cc\u062f \u0648\u0627\u0642\u0639 \u0634\u0648\u062f\u061b \u0627\u0645\u0627 \u0627\u06cc\u0646 \u0646\u0631\u0645\u200c\u0627\u0641\u0632\u0627\u0631 \u06cc\u06a9 \u0645\u062d\u0635\u0648\u0644 \u062a\u062c\u0627\u0631\u06cc \u0646\u0628\u0648\u062f \u0628\u0647 \u0637\u0648\u0631\u06cc \u06a9\u0647 \u0627\u06cc\u0646 \u062f\u0648 \u0628\u0631\u0627\u062f\u0631 \u0622\u0646 \u0631\u0627 \u0628\u0631\u0627\u06cc \u0627\u0647\u062f\u0627\u0641 \u0634\u062e\u0635\u06cc \u062e\u0648\u062f \u0646\u0648\u0634\u062a\u0647 \u0628\u0648\u062f\u0646\u062f.<\/span><!--more--><\/p>\n<p style=\"text-align: justify;\"><span style=\"font-size: 16px;\">\u0627\u06cc\u0646 \u0628\u0631\u0646\u0627\u0645\u0647 \u06a9\u0647 Display \u0646\u0627\u0645 \u062f\u0627\u0634\u062a\u060c \u0628\u0647 \u062a\u062f\u0631\u06cc\u062c \u06af\u0633\u062a\u0631\u062f\u0647\u200c\u062a\u0631 \u0648 \u062a\u062e\u0635\u0635\u06cc\u200c\u062a\u0631 \u0634\u062f \u0648 \u0633\u0631\u0627\u0646\u062c\u0627\u0645 \u062f\u0631 \u062a\u0627\u0628\u0633\u062a\u0627\u0646 \u0633\u0627\u0644 \u06f1\u06f9\u06f8\u06f8 \u0628\u0631\u0627\u062f\u0631\u0627\u0646 \u0646\u0648\u0644 \u0628\u0647 \u0627\u06cc\u0646 \u0646\u062a\u06cc\u062c\u0647 \u0631\u0633\u06cc\u062f\u0646\u062f \u06a9\u0647 \u0645\u06cc\u200c\u062a\u0648\u0627\u0646 \u0622\u0646 \u0631\u0627 \u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u06cc\u06a9 \u0645\u062d\u0635\u0648\u0644 \u062a\u062c\u0627\u0631\u06cc \u0645\u0639\u062a\u0628\u0631 \u0628\u0647 \u0628\u0627\u0632\u0627\u0631 \u0639\u0631\u0636\u0647 \u0646\u0645\u0648\u062f\u061b \u0627\u0632 \u0627\u06cc\u0646 \u0631\u0648\u060c \u0646\u0627\u0645 \u0622\u0646 \u0631\u0627 \u0628\u0647 Photoshop \u062a\u063a\u06cc\u06cc\u0631 \u062f\u0627\u062f\u0647 \u0648 \u062c\u0633\u062a\u062c\u0648 \u0628\u0631\u0627\u06cc \u06cc\u0627\u0641\u062a\u0646 \u0634\u0631\u06a9\u062a\u06cc \u062c\u0647\u062a \u062a\u0648\u0632\u06cc\u0639 \u0622\u0646 \u0631\u0627 \u0622\u063a\u0627\u0632 \u06a9\u0631\u062f\u0646\u062f \u06a9\u0647 \u062f\u0631 \u0646\u0647\u0627\u06cc\u062a \u062a\u0648\u0627\u0646\u0633\u062a\u0646\u062f \u0627\u0632 \u0637\u0631\u06cc\u0642 \u06cc\u06a9 \u0634\u0631\u06a9\u062a \u062a\u0648\u0644\u06cc\u062f \u0627\u0650\u0633\u06a9\u0646\u0631 \u0628\u0647 \u0646\u0627\u0645 Barneyscan XP\u060c \u062d\u062f\u0648\u062f \u06f2\u06f0\u06f0 \u06a9\u067e\u06cc \u0627\u0632 \u0627\u06cc\u0646 \u0646\u0631\u0645\u200c\u0627\u0641\u0632\u0627\u0631 \u0631\u0627 \u0628\u0647 \u0641\u0631\u0648\u0634 \u0628\u0631\u0633\u0627\u0646\u0646\u062f.<\/span><\/p>\n<p style=\"text-align: justify;\"><span style=\"font-size: 16px;\">\u0645\u0648\u0641\u0642\u06cc\u062a \u0641\u0648\u0642\u200c\u0627\u0644\u0639\u0627\u062f\u0647\u0654 \u0641\u062a\u0648\u0634\u0627\u067e \u0647\u0646\u06af\u0627\u0645\u06cc \u0631\u0642\u0645 \u062e\u0648\u0631\u062f \u06a9\u0647 \u0634\u0631\u06a9\u062a Adobe \u062a\u0635\u0645\u06cc\u0645 \u06af\u0631\u0641\u062a \u062a\u0627 \u0628\u0631\u0627\u06cc \u062a\u0648\u0632\u06cc\u0639 \u0646\u0633\u062e\u0647\u200c\u0654 \u067e\u06cc\u0634\u0631\u0641\u062a\u0647\u200c\u062a\u0631\u06cc \u0627\u0632 \u0627\u06cc\u0646 \u0646\u0631\u0645\u200c\u0627\u0641\u0632\u0627\u0631\u060c \u0633\u0631\u0645\u0627\u06cc\u0647\u200c\u06af\u0630\u0627\u0631\u06cc \u06a9\u0646\u062f\u061b \u0627\u06cc\u0646 \u062a\u0635\u0645\u06cc\u0645 \u062f\u0631 \u0622\u0648\u0631\u06cc\u0644 \u0633\u0627\u0644 \u06f1\u06f9\u06f8\u06f9 \u0646\u0647\u0627\u06cc\u06cc \u0634\u062f \u0648 \u0641\u0631\u0648\u0634 \u0646\u0633\u062e\u0647\u0654 \u06f1\u066b\u06f0 \u0646\u0631\u0645\u200c\u0627\u0641\u0632\u0627\u0631 \u0641\u062a\u0648\u0634\u0627\u067e \u062f\u0631 \u0627\u0648\u0627\u06cc\u0644 \u0633\u0627\u0644\u06f1\u06f9\u06f9\u06f0 \u062a\u0648\u0633\u0637 \u0627\u062f\u0648\u0628\u06cc \u0622\u063a\u0627\u0632 \u0634\u062f.<\/span><\/p>\n<p style=\"text-align: justify;\"><span style=\"font-size: 16px;\">\u0646\u0633\u062e\u0647\u0654 \u06f1.\u06f0 \u0646\u0631\u0645\u200c\u0627\u0641\u0632\u0627\u0631 \u0641\u062a\u0648\u0634\u0627\u067e \u0627\u0633\u0627\u0633\u0627\u064b \u0628\u0647 \u0632\u0628\u0627\u0646 \u067e\u0627\u0633\u06a9\u0627\u0644 \u0648 \u0628\u0631\u0627\u06cc \u0633\u06cc\u0633\u062a\u0645\u200c\u0639\u0627\u0645\u0644 \u0645\u06a9\u06cc\u0646\u062a\u0627\u0634 \u0627\u067e\u0644 \u0646\u0648\u0634\u062a\u0647 \u0634\u062f\u0647\u200c \u0628\u0648\u062f\u061b \u0627\u0644\u0628\u062a\u0647 \u062f\u0631 \u0645\u0648\u0627\u0631\u062f\u06cc \u06a9\u0647 \u0631\u0627\u0646\u062f\u0645\u0627\u0646 \u0627\u062c\u0631\u0627\u06cc \u06a9\u062f\u0647\u0627 \u0627\u0647\u0645\u06cc\u062a \u0628\u06cc\u0634\u062a\u0631\u06cc \u067e\u06cc\u062f\u0627 \u0645\u06cc\u200c\u06a9\u0631\u062f\u060c \u0627\u0632 \u0632\u0628\u0627\u0646 \u0645\u0627\u0634\u06cc\u0646 \u0628\u0631\u0627\u06cc \u0631\u06cc\u0632\u067e\u0631\u062f\u0627\u0632\u0646\u062f\u0647\u0654 Motorola 68000 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0634\u062f\u0647\u200c \u0628\u0648\u062f.<\/span><\/p>\n<p style=\"text-align: justify;\"><span style=\"font-size: 16px;\">\u062f\u0631\u200c \u0648\u0627\u0642\u0639\u060c \u0647\u0645\u200c\u0632\u0645\u0627\u0646 \u06a9\u0647 \u062a\u0648\u0645\u0627\u0633 \u0628\u0631 \u0631\u0648\u06cc \u0628\u0631\u0646\u0627\u0645\u0647\u0654 \u0627\u0635\u0644\u06cc \u06a9\u0627\u0631 \u0645\u06cc\u200c\u06a9\u0631\u062f\u060c \u0628\u0631\u0627\u062f\u0631\u0634 (\u062c\u0627\u0646) \u062f\u0631\u06af\u06cc\u0631 \u0646\u0648\u0634\u062a\u0646 \u067e\u0644\u0627\u06af\u06cc\u0646\u200c\u0647\u0627\u06cc \u0645\u062a\u0639\u062f\u062f \u067e\u0631\u062f\u0627\u0632\u0634 \u062a\u0635\u0648\u06cc\u0631 \u0628\u0631\u0627\u06cc \u0627\u06cc\u0646 \u0628\u0631\u0646\u0627\u0645\u0647 \u0628\u0648\u062f \u062a\u0627 \u0627\u06cc\u0646\u06a9\u0647 \u0641\u062a\u0648\u0634\u0627\u067e \u0628\u0647 \u0645\u0631\u0648\u0631 \u0632\u0645\u0627\u0646 \u0628\u0647 \u0686\u06cc\u0632\u06cc \u062a\u0628\u062f\u06cc\u0644 \u0634\u062f \u06a9\u0647 \u0627\u0645\u0631\u0648\u0632\u0647 \u062f\u0631 \u0635\u0646\u0639\u062a \u0646\u0631\u0645\u200c\u0627\u0641\u0632\u0627\u0631\u0647\u0627\u06cc \u0648\u06cc\u0631\u0627\u06cc\u0634 \u062a\u0635\u0648\u06cc\u0631\u060c \u0628\u06cc\u200c\u0631\u0642\u06cc\u0628 \u0627\u0633\u062a.<\/span><\/p>\n<p style=\"text-align: justify;\"><strong><span style=\"font-size: 16px;\">\u0627\u0646\u062a\u0634\u0627\u0631 \u0633\u0648\u0631\u0633\u200c\u06a9\u062f \u0641\u062a\u0648\u0634\u0627\u067e \u0646\u0633\u062e\u0647\u0654 \u06f1 \u0628\u0647 \u0635\u0648\u0631\u062a \u0627\u067e\u0646\u200c\u0633\u0648\u0631\u0633<\/span><\/strong><br \/>\n<span style=\"font-size: 16px;\"><a href=\"http:\/\/www.computerhistory.org\/atchm\/adobe-photoshop-source-code\/\">Computer History Museum<\/a>\u00a0(\u0645\u0648\u0632\u0647\u0654\u200c \u062a\u0627\u0631\u06cc\u062e \u06a9\u0627\u0645\u067e\u06cc\u0648\u062a\u0631) \u0628\u0627 \u06a9\u0633\u0628 \u0645\u062c\u0648\u0632 \u0627\u0632 \u06a9\u0645\u067e\u0627\u0646\u06cc Adobe Systems\u060c \u0633\u0648\u0631\u0633\u200c\u06a9\u062f \u0646\u0633\u062e\u0647\u0654\u200c \u06f1\u066b\u06f0\u066b\u06f1 \u0646\u0631\u0645\u200c\u0627\u0641\u0632\u0627\u0631 \u0641\u062a\u0648\u0634\u0627\u067e (\u06a9\u0647 \u062f\u0631 \u0633\u0627\u0644 \u06f1\u06f9\u06f9\u06f0 \u062a\u0648\u0644\u06cc\u062f \u0634\u062f) \u0631\u0627 \u0628\u0631\u0627\u06cc \u0627\u0647\u062f\u0627\u0641 \u063a\u06cc\u0631\u062a\u062c\u0627\u0631\u06cc \u0645\u0646\u062a\u0634\u0631 \u0646\u0645\u0648\u062f\u0647 \u0627\u0633\u062a. \u0633\u0648\u0631\u0633\u200c\u06a9\u062f \u0645\u0646\u062a\u0634\u0631 \u0634\u062f\u0647\u060c \u0647\u0645\u0647\u0654 \u06a9\u062f\u0647\u0627\u06cc \u0627\u06cc\u0646 \u0646\u0633\u062e\u0647 \u0627\u0632 \u0627\u06cc\u0646 \u0646\u0631\u0645\u200c\u0627\u0641\u0632\u0627\u0631 \u0628\u0647 \u062c\u0632 \u0644\u0627\u06cc\u0628\u0631\u0631\u06cc \u0627\u067e\u0644\u06cc\u06a9\u06cc\u0634\u0646\u200c\u0647\u0627\u06cc MacApp -\u06a9\u0647 \u062a\u062d\u062a \u0645\u062c\u0648\u0632 \u0627\u067e\u0644 \u0627\u0633\u062a- \u0631\u0627 \u062f\u0631 \u0628\u0631 \u0645\u06cc\u200c\u06af\u06cc\u0631\u062f. \u0627\u06cc\u0646 \u0633\u0648\u0631\u0633\u200c\u06a9\u062f \u0634\u0627\u0645\u0644 \u06f1\u06f7\u06f9 \u0641\u0627\u06cc\u0644 \u0627\u0633\u062a \u06a9\u0647 \u062f\u0631 \u06cc\u06a9 \u0641\u0648\u0644\u062f\u0631 \u0632\u06cc\u067e \u0642\u0631\u0627\u0631 \u062f\u0627\u0631\u0646\u062f \u0648 \u0627\u06cc\u0646 \u06f1\u06f7\u06f9 \u0641\u0627\u06cc\u0644 \u062d\u0627\u0648\u06cc \u062d\u062f\u0648\u062f \u06f1\u06f2\u06f8\u06f0\u06f0\u06f0 \u062e\u0637 \u06a9\u062f \u0647\u0633\u062a\u0646\u062f \u06a9\u0647 \u0639\u0645\u062f\u062a\u0627\u064b \u06a9\u0627\u0645\u0646\u062a\u200c\u0646\u0648\u06cc\u0633\u06cc \u062f\u0631 \u0645\u0648\u0631\u062f \u0622\u0646\u200c\u0647\u0627 \u0635\u0648\u0631\u062a \u0646\u06af\u0631\u0641\u062a\u0647 \u0627\u0645\u0627 \u0627\u0632 \u0633\u0627\u062e\u062a\u0627\u0631 \u062e\u0648\u0628\u06cc \u0628\u0631\u062e\u0648\u0631\u062f\u0627\u0631\u0646\u062f! \u0628\u0631 \u0645\u0628\u0646\u0627\u06cc \u062a\u0639\u062f\u0627\u062f \u062e\u0637\u0648\u0637\u060c \u062d\u062f\u0648\u062f \u06f7\u06f5\u066a \u0627\u0632 \u0627\u06cc\u0646 \u06a9\u062f\u0647\u0627 \u0628\u0647 \u0632\u0628\u0627\u0646\u00a0\u067e\u0627\u0633\u06a9\u0627\u0644\u060c \u062d\u062f\u0648\u062f \u06f1\u06f5\u066a \u0628\u0647 \u0632\u0628\u0627\u0646\u00a0\u0627\u0633\u0650\u0645\u0628\u0644\u06cc\u00a0\u0646\u0648\u0634\u062a\u0647 \u0634\u062f\u0647 \u0648 \u0628\u0642\u06cc\u0647\u0654 \u0622\u0646 \u0631\u0627 \u0627\u0646\u0648\u0627\u0639 \u0645\u062e\u062a\u0644\u0641\u06cc \u0627\u0632 \u062f\u0627\u062f\u0647\u200c\u0647\u0627\u06cc \u0645\u0631\u062a\u0628\u0637 \u062a\u0634\u06a9\u06cc\u0644 \u0645\u06cc\u200c\u062f\u0647\u0646\u062f.<\/span><\/p>\n<p style=\"text-align: justify;\"><span style=\"font-size: 16px;\">\u0628\u0627\u06cc\u062f \u062a\u0648\u062c\u0647 \u062f\u0627\u0634\u062a\u0647 \u0628\u0627\u0634\u06cc\u062f \u06a9\u0647 \u0628\u0631\u0627\u06cc <a href=\"http:\/\/www.computerhistory.org\/atchm\/photoshop-software-license-agreement\/\">\u062f\u0627\u0646\u0644\u0648\u062f \u0633\u0648\u0631\u0633\u200c\u06a9\u062f \u0627\u067e\u0646\u200c\u0633\u0648\u0631\u0633 \u0641\u062a\u0648\u0634\u0627\u067e \u0646\u0633\u062e\u0647\u0654 \u06f1<\/a>\u060c \u0644\u0627\u0632\u0645 \u0627\u0633\u062a \u0645\u0648\u0627\u0631\u062f \u0630\u06a9\u0631 \u0634\u062f\u0647 \u062f\u0631 \u0645\u062c\u0648\u0632\u060c \u0647\u0645\u0686\u0648\u0646 \u0645\u0645\u0646\u0648\u0639\u06cc\u062a \u0627\u0633\u062a\u0641\u0627\u062f\u0647\u0654 \u062a\u062c\u0627\u0631\u06cc \u0627\u0632 \u0622\u0646 \u0648 \u0647\u0645\u0686\u0646\u06cc\u0646 \u0645\u0645\u0646\u0648\u0639\u06cc\u062a \u0627\u0646\u062a\u0634\u0627\u0631 \u0622\u0646 \u062f\u0631 \u0648\u0628 \u0648 \u06cc\u0627 \u0627\u0639\u0637\u0627\u06cc \u0645\u062c\u0648\u0632 \u0628\u0647 \u0634\u062e\u0635 \u062b\u0627\u0644\u062b \u0631\u0627 \u0628\u067e\u0630\u06cc\u0631\u06cc\u062f. \u0648\u0644\u06cc \u0645\u0646 \u0627\u06cc\u0646 \u0628\u0646\u062f \u0627\u0632 \u0642\u0631\u062f\u0627\u062f \u0631\u0627 \u0646\u0642\u0636 \u0645\u06cc\u06a9\u0646\u0645 \u0648 <a href=\"https:\/\/mehdisalimi.ir\/Download\/Photoshop-v.1.0.1-Source-Code.zip\">\u0644\u06cc\u0646\u06a9 \u062f\u0627\u0646\u0644\u0648\u062f \u0645\u0633\u062a\u0642\u06cc\u0645<\/a> \u0641\u0627\u06cc\u0644 \u0647\u0627 \u0631\u0627 \u062f\u0631 \u0627\u062e\u062a\u06cc\u0627\u0631\u062a\u0627\u0646 \u0642\u0631\u0627\u0631 \u0645\u06cc\u062f\u0647\u0645. \u0627\u06cc\u0646\u06a9\u0647 \u0627\u0632 \u0627\u06cc\u0646 \u06a9\u062f \u0647\u0627 \u0686\u0647 \u0637\u0648\u0631 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u06a9\u0646\u06cc\u062f\u060c \u0645\u0631\u0628\u0648\u0637 \u0628\u0647 \u0634\u062e\u0635 \u062e\u0648\u062f\u062a\u0627\u0646 \u0645\u06cc \u0634\u0648\u062f!<\/span><\/p>\n<p style=\"text-align: justify;\"><span style=\"font-size: 16px;\">\u06a9\u062f \u0645\u0631\u0628\u0648\u0637 \u0628\u0647 \u0628\u062e\u0634 Draw<\/span><\/p>\n<pre class=\"lang:default decode:true\" title=\"\u06a9\u062f \u0645\u0631\u0628\u0648\u0637 \u0628\u0647 \u0628\u062e\u0634 Draw\">{Photoshop version 1.0.1, file: UDraw.p\r\n  Computer History Museum, www.computerhistory.org\r\n  This material is (C)Copyright 1990 Adobe Systems Inc.\r\n  It may not be distributed to third parties.\r\n  It is licensed for non-commercial use according to \r\n  www.computerhistory.org\/softwarelicense\/photoshop\/ }\r\n\r\nUNIT UDraw;\r\n\r\nINTERFACE\r\n\r\nUSES\r\n\t{$LOAD MacIntf.LOAD}\r\n\tMemTypes, QuickDraw, OSIntf, ToolIntf, PackIntf,\r\n\t{$LOAD UMacApp.LOAD}\r\n\tUObject, UList, UMacApp,\r\n\t{$LOAD UPhotoshop.LOAD}\r\n\tPaletteMgr, UConstants, UVMemory, UPhotoshop,\r\n\t{$LOAD}\r\n\tUDialog, UBWDialog, UCommands, UGhost, UPressure;\r\n\r\nTYPE\r\n\r\n\tTMarkingTool = OBJECT (TBufferCommand)\r\n\r\n\t\tfChannel: INTEGER;\r\n\r\n\t\tfMarkedArea: Rect;\r\n\r\n\t\tfCachedArea: Rect;\r\n\r\n\t\tfCacheSize: Point;\r\n\r\n\t\tfLastPoint: Point;\r\n\r\n\t\tfPixelAlign: BOOLEAN;\r\n\t\tfConstrainH: BOOLEAN;\r\n\t\tfConstrainV: BOOLEAN;\r\n\r\n\t\tfLowerPage: INTEGER;\r\n\t\tfUpperPage: INTEGER;\r\n\r\n\t\tfPhysicalSize: INTEGER;\r\n\r\n\t\tfFailMessage: LONGINT;\r\n\r\n\t\tfAlphaMap: TLookUpTable;\r\n\t\tfAlphaChannel: TVMArray;\r\n\r\n\t\tfAuxCursor: BOOLEAN;\r\n\t\tfAuxLocation: Point;\r\n\t\tfAuxView: TImageView;\r\n\r\n\t\tPROCEDURE TMarkingTool.IMarkingTool (view: TImageView;\r\n\t\t\t\t\t\t\t\t\t\t\t itsCommand: INTEGER;\r\n\t\t\t\t\t\t\t\t\t\t\t cacheSize: Point;\r\n\t\t\t\t\t\t\t\t\t\t\t failMessage: LONGINT;\r\n\t\t\t\t\t\t\t\t\t\t\t needAlpha: BOOLEAN);\r\n\r\n\t\tPROCEDURE TMarkingTool.Free; OVERRIDE;\r\n\r\n\t\tPROCEDURE TMarkingTool.TrackFeedBack (anchorPoint: Point;\r\n\t\t\t\t\t\t\t\t\t\t\t  nextPoint: Point;\r\n\t\t\t\t\t\t\t\t\t\t\t  turnItOn: BOOLEAN;\r\n\t\t\t\t\t\t\t\t\t\t\t  mouseDidMove: BOOLEAN); OVERRIDE;\r\n\r\n\t\tPROCEDURE TMarkingTool.TrackConstrain (anchorPoint: Point;\r\n\t\t\t\t\t\t\t\t\t\t\t   previousPoint: Point;\r\n\t\t\t\t\t\t\t\t\t\t\t   VAR nextPoint: Point); OVERRIDE;\r\n\r\n\t\tPROCEDURE TMarkingTool.BuildAlpha (lower, upper: INTEGER);\r\n\r\n\t\tPROCEDURE TMarkingTool.SaveLines (lower, upper: INTEGER);\r\n\r\n\t\tPROCEDURE TMarkingTool.AddToMarked (r: Rect);\r\n\r\n\t\tPROCEDURE TMarkingTool.DrawAuxCursor (pt: Point);\r\n\r\n\t\tPROCEDURE TMarkingTool.FlushCache;\r\n\r\n\t\tPROCEDURE TMarkingTool.AddToCache (r: Rect);\r\n\r\n\t\tPROCEDURE TMarkingTool.FixReleasePoint (anchorPoint: Point;\r\n\t\t\t\t\t\t\t\t\t\t\t\tVAR nextPoint: Point);\r\n\r\n\t\tPROCEDURE TMarkingTool.SwapRect (r: Rect; iArray, bArray: TVMArray);\r\n\r\n\t\tPROCEDURE TMarkingTool.SwapMarkedArea;\r\n\r\n\t\tPROCEDURE TMarkingTool.FlushImage;\r\n\r\n\t\tPROCEDURE TMarkingTool.RecoverFailure;\r\n\r\n\t\tPROCEDURE TMarkingTool.DoIt; OVERRIDE;\r\n\r\n\t\tPROCEDURE TMarkingTool.UndoIt; OVERRIDE;\r\n\r\n\t\tPROCEDURE TMarkingTool.RedoIt; OVERRIDE;\r\n\r\n\t\tEND;\r\n\r\n\tTEraserTool = OBJECT (TMarkingTool)\r\n\r\n\t\tfMagic: BOOLEAN;\r\n\r\n\t\tfColor1: INTEGER;\r\n\t\tfColor2: INTEGER;\r\n\t\tfColor3: INTEGER;\r\n\r\n\t\tPROCEDURE TEraserTool.IEraserTool (view: TImageView; magic: BOOLEAN);\r\n\r\n\t\tFUNCTION TEraserTool.TrackMouse\r\n\t\t\t\t\t\t(aTrackPhase: TrackPhase;\r\n\t\t\t\t\t\t VAR anchorPoint: Point;\r\n\t\t\t\t\t\t VAR previousPoint: Point;\r\n\t\t\t\t\t\t VAR nextPoint: Point;\r\n\t\t\t\t\t\t mouseDidMove: BOOLEAN): TCommand; OVERRIDE;\r\n\r\n\t\tEND;\r\n\r\n\tTTip = RECORD\r\n\r\n\t\tfSize: Point;\r\n\t\tfSpot: Point;\r\n\r\n\t\tfMask: Handle;\r\n\t\tfMask2: Handle;\r\n\r\n\t\tfData: ARRAY [0..3] OF Handle\r\n\r\n\t\tEND;\r\n\r\n\tTDrawingMode = (NormalDrawing, ColorOnly, DarkenOnly, LightenOnly);\r\n\r\n\tTDrawingTool = OBJECT (TMarkingTool)\r\n\r\n\t\tfTip: TTip;\r\n\r\n\t\tfMode: TDrawingMode;\r\n\r\n\t\tfSpacing: INTEGER;\r\n\r\n\t\tfFadeout: INTEGER;\r\n\r\n\t\tfDelay: INTEGER;\r\n\r\n\t\tfPressureMode: INTEGER;\r\n\r\n\t\tfDip: BOOLEAN;\r\n\r\n\t\tfMixMap: TLookUpTable;\r\n\r\n\t\tfDrawings: LONGINT;\r\n\r\n\t\tfLastDrawTime: LONGINT;\r\n\r\n\t\tfSpacingCounter: INTEGER;\r\n\r\n\t\tfStampMethod: INTEGER;\r\n\r\n\t\tfImpressCounter: INTEGER;\r\n\t\tfImpressTimer  : LONGINT;\r\n\r\n\t\tfTextureNoise: Handle;\r\n\r\n\t\tfStampOffset: Point;\r\n\r\n\t\tfFore: ARRAY [1..3] OF INTEGER;\r\n\t\tfBack: ARRAY [1..3] OF INTEGER;\r\n\r\n\t\tPROCEDURE TDrawingTool.IDrawingTool (view: TImageView;\r\n\t\t\t\t\t\t\t\t\t\t\t itsCommand: INTEGER;\r\n\t\t\t\t\t\t\t\t\t\t\t VAR tip: TTip;\r\n\t\t\t\t\t\t\t\t\t\t\t mode: TDrawingMode;\r\n\t\t\t\t\t\t\t\t\t\t\t spacing: INTEGER;\r\n\t\t\t\t\t\t\t\t\t\t\t fadeout: INTEGER;\r\n\t\t\t\t\t\t\t\t\t\t\t rate: INTEGER;\r\n\t\t\t\t\t\t\t\t\t\t\t failMessage: LONGINT;\r\n\t\t\t\t\t\t\t\t\t\t\t needAlpha: BOOLEAN);\r\n\r\n\t\tPROCEDURE TDrawingTool.Free; OVERRIDE;\r\n\r\n\t\tPROCEDURE TDrawingTool.FindMask (offset: LONGINT; r: Rect);\r\n\r\n\t\tPROCEDURE TDrawingTool.BlurOrSharpen (dataPtr: Ptr;\r\n\t\t\t\t\t\t\t\t\t\t\t  offset: LONGINT;\r\n\t\t\t\t\t\t\t\t\t\t\t  r: Rect;\r\n\t\t\t\t\t\t\t\t\t\t\t  band: INTEGER;\r\n\t\t\t\t\t\t\t\t\t\t\t  sharpen: BOOLEAN);\r\n\r\n\t\tPROCEDURE TDrawingTool.SmudgeBand (dataPtr: Ptr;\r\n\t\t\t\t\t\t\t\t\t\t   offset: LONGINT;\r\n\t\t\t\t\t\t\t\t\t\t   r: Rect;\r\n\t\t\t\t\t\t\t\t\t\t   band: INTEGER);\r\n\r\n\t\tPROCEDURE TDrawingTool.MarkBand (dataPtr: Ptr;\r\n\t\t\t\t\t\t\t\t\t\t offset: LONGINT;\r\n\t\t\t\t\t\t\t\t\t\t r: Rect;\r\n\t\t\t\t\t\t\t\t\t\t band: INTEGER);\r\n\r\n\t\tPROCEDURE TDrawingTool.MarkRGB (rDataPtr: Ptr;\r\n\t\t\t\t\t\t\t\t\t\tgDataPtr: Ptr;\r\n\t\t\t\t\t\t\t\t\t\tbDataPtr: Ptr;\r\n\t\t\t\t\t\t\t\t\t\toffset: LONGINT;\r\n\t\t\t\t\t\t\t\t\t\tr: Rect);\r\n\r\n\t\tPROCEDURE TDrawingTool.LoadOverlap (r: Rect;\r\n\t\t\t\t\t\t\t\t\t\t\tsrcArray1: TVMArray;\r\n\t\t\t\t\t\t\t\t\t\t\tsrcArray2: TVMArray;\r\n\t\t\t\t\t\t\t\t\t\t\tsrcArray3: TVMArray);\r\n\r\n\t\tPROCEDURE TDrawingTool.LoadCloneTip (r: Rect);\r\n\r\n\t\tPROCEDURE TDrawingTool.LoadRevertTip (r: Rect);\r\n\r\n\t\tPROCEDURE TDrawingTool.LoadTextureTip;\r\n\r\n\t\tPROCEDURE TDrawingTool.LoadPatternTip (r: Rect);\r\n\r\n\t\tPROCEDURE TDrawingTool.LoadImpressTip (pt: Point);\r\n\r\n\t\tFUNCTION TDrawingTool.TrackMouse\r\n\t\t\t\t\t\t(aTrackPhase: TrackPhase;\r\n\t\t\t\t\t\t VAR anchorPoint: Point;\r\n\t\t\t\t\t\t VAR previousPoint: Point;\r\n\t\t\t\t\t\t VAR nextPoint: Point;\r\n\t\t\t\t\t\t mouseDidMove: BOOLEAN): TCommand; OVERRIDE;\r\n\r\n\t\tEND;\r\n\r\n\tTPencilTool = OBJECT (TDrawingTool)\r\n\r\n\t\tfAutoErase: BOOLEAN;\r\n\r\n\t\tPROCEDURE TPencilTool.IPencilTool (view: TImageView; pt: Point);\r\n\r\n\t\tEND;\r\n\r\n\tTBrushTool = OBJECT (TDrawingTool)\r\n\r\n\t\tPROCEDURE TBrushTool.IBrushTool (view: TImageView);\r\n\r\n\t\tEND;\r\n\r\n\tTAirbrushTool = OBJECT (TDrawingTool)\r\n\r\n\t\tPROCEDURE TAirbrushTool.IAirbrushTool (view: TImageView);\r\n\r\n\t\tEND;\r\n\r\n\tTBlurTool = OBJECT (TDrawingTool)\r\n\r\n\t\tPROCEDURE TBlurTool.IBlurTool (view: TImageView);\r\n\r\n\t\tEND;\r\n\r\n\tTSharpenTool = OBJECT (TDrawingTool)\r\n\r\n\t\tPROCEDURE TSharpenTool.ISharpenTool (view: TImageView);\r\n\r\n\t\tEND;\r\n\r\n\tTSmudgeTool = OBJECT (TDrawingTool)\r\n\r\n\t\tPROCEDURE TSmudgeTool.ISmudgeTool (view: TImageView; dip: BOOLEAN);\r\n\r\n\t\tEND;\r\n\r\n\tTStampTool = OBJECT (TDrawingTool)\r\n\r\n\t\tPROCEDURE TStampTool.IStampTool (view: TImageView; theMsg: LONGINT);\r\n\r\n\t\tEND;\r\n\r\n\tTEraseAll = OBJECT (TBufferCommand)\r\n\r\n\t\tfChannel: INTEGER;\r\n\r\n\t\tPROCEDURE TEraseAll.IEraseAll (view: TImageView);\r\n\r\n\t\tPROCEDURE TEraseAll.DoIt; OVERRIDE;\r\n\r\n\t\tPROCEDURE TEraseAll.UndoIt; OVERRIDE;\r\n\r\n\t\tPROCEDURE TEraseAll.RedoIt; OVERRIDE;\r\n\r\n\t\tEND;\r\n\r\n\tTBrushesView = OBJECT (TView)\r\n\r\n\t\tfShapeID: INTEGER;\r\n\r\n\t\tfCustomRect: Rect;\r\n\r\n\t\tPROCEDURE TBrushesView.IBrushesView;\r\n\r\n\t\tPROCEDURE TBrushesView.HighlightShape (turnOn: BOOLEAN);\r\n\r\n\t\tFUNCTION TBrushesView.DoMouseCommand\r\n\t\t\t\t(VAR downLocalPoint: Point;\r\n\t\t\t\t VAR info: EventInfo;\r\n\t\t\t\t VAR hysteresis: Point): TCommand; OVERRIDE;\r\n\r\n\t\tPROCEDURE TBrushesView.Draw (area: Rect); OVERRIDE;\r\n\r\n\t\tEND;\r\n\r\n\tTShapeDialog = OBJECT (TBWDialog)\r\n\r\n\t\tfShapeID: INTEGER;\r\n\r\n\t\tfShapesRect: Rect;\r\n\t\tfCustomRect: Rect;\r\n\r\n\t\tPROCEDURE TShapeDialog.IShapeDialog (dialogID, shapeID: INTEGER);\r\n\r\n\t\tPROCEDURE TShapeDialog.HighlightShape (turnOn: BOOLEAN);\r\n\r\n\t\tPROCEDURE TShapeDialog.DrawAmendments (theItem: INTEGER); OVERRIDE;\r\n\r\n\t\tPROCEDURE TShapeDialog.DoFilterEvent (VAR anEvent: EventRecord;\r\n\t\t\t\t\t\t\t\t\t\t\t  VAR itemHit: INTEGER;\r\n\t\t\t\t\t\t\t\t\t\t\t  VAR handledIt: BOOLEAN;\r\n\t\t\t\t\t\t\t\t\t\t\t  VAR doReturn: BOOLEAN); OVERRIDE;\r\n\r\n\t\tEND;\r\n\r\nPROCEDURE InitDrawing;\r\n\r\nFUNCTION DoEraserTool (view: TImageView; magic: BOOLEAN): TCommand;\r\n\r\nFUNCTION DoPencilTool (view: TImageView; pt: Point): TCommand;\r\n\r\nFUNCTION DoBrushTool (view: TImageView): TCommand;\r\n\r\nFUNCTION DoAirbrushTool (view: TImageView): TCommand;\r\n\r\nFUNCTION DoBlurTool (view: TImageView): TCommand;\r\n\r\nFUNCTION DoSharpenTool (view: TImageView): TCommand;\r\n\r\nFUNCTION DoSmudgeTool (view: TImageView; dip: BOOLEAN): TCommand;\r\n\r\nFUNCTION DoStampTool (view: TImageView): TCommand;\r\n\r\nFUNCTION DoStampPadTool (view: TImageView; pt: Point): TCommand;\r\n\r\nFUNCTION DoEraseAll (view: TImageView): TCommand;\r\n\r\nFUNCTION BrushesVisible: BOOLEAN;\r\n\r\nPROCEDURE ShowBrushes (visible: BOOLEAN);\r\n\r\nPROCEDURE UpdateBrush;\r\n\r\nPROCEDURE DoPencilOptions;\r\n\r\nPROCEDURE DoBrushOptions;\r\n\r\nPROCEDURE DoAirbrushOptions;\r\n\r\nPROCEDURE DoBlurOptions;\r\n\r\nPROCEDURE DoSharpenOptions;\r\n\r\nPROCEDURE DoSmudgeOptions;\r\n\r\nPROCEDURE DoStampOptions;\r\n\r\nPROCEDURE DefineBrush (view: TImageView);\r\n\r\nPROCEDURE DefinePattern (view: TImageView);\r\n\r\nIMPLEMENTATION\r\n\r\n{$I UAssembly.a.inc}\r\n{$I UDraw.a.inc}\r\n{$I UFloat.a.inc}\r\n{$I USelect.p.inc}\r\n\r\nCONST\r\n\r\n\tkTipSize = 25;\r\n\r\n\tkMaxTipSize = 64;\r\n\tkMaxTipArea = kMaxTipSize * kMaxTipSize;\r\n\r\n\tkShapesPictID = 2000;\r\n\r\n\tkClone1Method\t= \u06f0;\r\n\tkClone2Method\t= \u06f1;\r\n\tkRevertMethod\t= \u06f2;\r\n\tkTextureMethod\t= \u06f3;\r\n\tkPattern1Method = 4;\r\n\tkPattern2Method = 5;\r\n\tkImpressMethod\t= \u06f6;\r\n\r\n\tkUndefinedOption = -32768;\r\n\r\nTYPE\r\n\r\n\tTTipBuffer = PACKED ARRAY [0..kMaxTipArea-1] OF CHAR;\r\n\r\n\tTTipTemplate = RECORD\r\n\t\tsize: Point;\r\n\t\tspot: Point;\r\n\t\tdata: ARRAY [0..0] OF INTEGER\r\n\t\tEND;\r\n\r\n\tPTipTemplate = ^TTipTemplate;\r\n\tHTipTemplate = ^PTipTemplate;\r\n\r\n\tTToolOptions = RECORD\r\n\t\tshapeID  : INTEGER;\r\n\t\tmode\t : TDrawingMode;\r\n\t\tspacing  : INTEGER;\r\n\t\tfadeout  : INTEGER;\r\n\t\trate\t : INTEGER;\r\n\t\tpressure : INTEGER;\r\n\t\tmethod\t : INTEGER;\r\n\t\tcheck1\t : INTEGER;\r\n\t\twacom\t : INTEGER\r\n\t\tEND;\r\n\r\nVAR\r\n\r\n\tgHaveTexture: BOOLEAN;\r\n\tgTexture: ARRAY [0..3] OF TLookUpTable;\r\n\r\n\tgCustomSize: Point;\r\n\tgCustomTip: TTipBuffer;\r\n\tgCustomIcon: Handle;\r\n\r\n\tgBrushesView: TBrushesView;\r\n\tgBrushesWindow: TGhostWindow;\r\n\r\n\tgPencilOptions\t: TToolOptions;\r\n\tgBrushOptions\t: TToolOptions;\r\n\tgAirbrushOptions: TToolOptions;\r\n\tgBlurOptions\t: TToolOptions;\r\n\tgSharpenOptions : TToolOptions;\r\n\tgSmudgeOptions\t: TToolOptions;\r\n\tgStampOptions\t: TToolOptions;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S AInit}\r\n\r\nPROCEDURE InitDrawing;\r\n\r\n\tBEGIN\r\n\r\n\tInitPressure;\r\n\r\n\tgHaveTexture := FALSE;\r\n\r\n\tgCustomSize := Point (0);\r\n\r\n\tgCustomIcon := NewHandle (128);\r\n\tFailNil (gCustomIcon);\r\n\r\n\tgPatternRect := gZeroRect;\r\n\r\n\tgPattern [0] := NIL;\r\n\tgPattern [1] := NIL;\r\n\tgPattern [2] := NIL;\r\n\tgPattern [3] := NIL;\r\n\r\n\tWITH gPencilOptions DO\r\n\t\tBEGIN\r\n\t\tshapeID   := 1;\r\n\t\tmode\t  := NormalDrawing;\r\n\t\tspacing   := 1;\r\n\t\tfadeout   := kUndefinedOption;\r\n\t\trate\t  := kUndefinedOption;\r\n\t\tpressure  := 100;\r\n\t\tmethod\t  := kUndefinedOption;\r\n\t\tcheck1\t  := \u06f0;\r\n\t\twacom\t  := ORD (gHavePressure)\r\n\t\tEND;\r\n\r\n\tWITH gBrushOptions DO\r\n\t\tBEGIN\r\n\t\tshapeID   := 4;\r\n\t\tmode\t  := NormalDrawing;\r\n\t\tspacing   := 1;\r\n\t\tfadeout   := 0;\r\n\t\trate\t  := \u06f0;\r\n\t\tpressure  := 100;\r\n\t\tmethod\t  := kUndefinedOption;\r\n\t\tcheck1\t  := kUndefinedOption;\r\n\t\twacom\t  := ORD (gHavePressure)\r\n\t\tEND;\r\n\r\n\tWITH gAirbrushOptions DO\r\n\t\tBEGIN\r\n\t\tshapeID   := 8;\r\n\t\tmode\t  := NormalDrawing;\r\n\t\tspacing   := 1;\r\n\t\tfadeout   := 0;\r\n\t\trate\t  := \u06f1\u06f0;\r\n\t\tpressure  := 50 + 50 * ORD (gHavePressure);\r\n\t\tmethod\t  := kUndefinedOption;\r\n\t\tcheck1\t  := kUndefinedOption;\r\n\t\twacom\t  := ORD (gHavePressure)\r\n\t\tEND;\r\n\r\n\tWITH gBlurOptions DO\r\n\t\tBEGIN\r\n\t\tshapeID   := 4;\r\n\t\tmode\t  := NormalDrawing;\r\n\t\tspacing   := 1;\r\n\t\tfadeout   := kUndefinedOption;\r\n\t\trate\t  := \u06f1\u06f0;\r\n\t\tpressure  := 50;\r\n\t\tmethod\t  := kUndefinedOption;\r\n\t\tcheck1\t  := kUndefinedOption;\r\n\t\twacom\t  := kUndefinedOption\r\n\t\tEND;\r\n\r\n\tWITH gSharpenOptions DO\r\n\t\tBEGIN\r\n\t\tshapeID   := 8;\r\n\t\tmode\t  := NormalDrawing;\r\n\t\tspacing   := 5;\r\n\t\tfadeout   := kUndefinedOption;\r\n\t\trate\t  := \u06f0;\r\n\t\tpressure  := 50;\r\n\t\tmethod\t  := kUndefinedOption;\r\n\t\tcheck1\t  := kUndefinedOption;\r\n\t\twacom\t  := kUndefinedOption\r\n\t\tEND;\r\n\r\n\tWITH gSmudgeOptions DO\r\n\t\tBEGIN\r\n\t\tshapeID   := 4;\r\n\t\tmode\t  := NormalDrawing;\r\n\t\tspacing   := 1;\r\n\t\tfadeout   := kUndefinedOption;\r\n\t\trate\t  := \u06f0;\r\n\t\tpressure  := 50;\r\n\t\tmethod\t  := kUndefinedOption;\r\n\t\tcheck1\t  := kUndefinedOption;\r\n\t\twacom\t  := kUndefinedOption\r\n\t\tEND;\r\n\r\n\tWITH gStampOptions DO\r\n\t\tBEGIN\r\n\t\tshapeID   := 8;\r\n\t\tmode\t  := NormalDrawing;\r\n\t\tspacing   := 1;\r\n\t\tfadeout   := kUndefinedOption;\r\n\t\trate\t  := kUndefinedOption;\r\n\t\tpressure  := 100;\r\n\t\tmethod\t  := kClone1Method;\r\n\t\tcheck1\t  := kUndefinedOption;\r\n\t\twacom\t  := kUndefinedOption\r\n\t\tEND;\r\n\r\n\tNEW (gBrushesView);\r\n\tFailNil (gBrushesView);\r\n\r\n\tgBrushesView.IBrushesView\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE FreeTip (VAR tip: TTip);\r\n\r\n\tBEGIN\r\n\r\n\tIF tip.fMask  &lt;&gt; NIL THEN DisposHandle (tip.fMask);\r\n\tIF tip.fMask2 &lt;&gt; NIL THEN DisposHandle (tip.fMask2);\r\n\r\n\tIF tip.fData [0] &lt;&gt; NIL THEN DisposHandle (tip.fData [0]);\r\n\tIF tip.fData [1] &lt;&gt; NIL THEN DisposHandle (tip.fData [1]);\r\n\tIF tip.fData [2] &lt;&gt; NIL THEN DisposHandle (tip.fData [2]);\r\n\tIF tip.fData [3] &lt;&gt; NIL THEN DisposHandle (tip.fData [3])\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE LoadTip (VAR tip: TTip; id: INTEGER; view: TImageView);\r\n\r\n\tVAR\r\n\t\tband: INTEGER;\r\n\t\tpixels: INTEGER;\r\n\t\ttemplate: HTipTemplate;\r\n\r\n\tBEGIN\r\n\r\n\tIF id = 0 THEN\r\n\t\tBEGIN\r\n\r\n\t\tIF gCustomSize.h = 0 THEN\r\n\t\t\tFailure (errNoCustomBrush, 0);\r\n\r\n\t\ttip.fSize := gCustomSize;\r\n\r\n\t\ttip.fSpot.h :=\tgCustomSize.h\t   DIV 2;\r\n\t\ttip.fSpot.v := (gCustomSize.v - 1) DIV 2\r\n\r\n\t\tEND\r\n\r\n\tELSE\r\n\t\tBEGIN\r\n\r\n\t\ttemplate := HTipTemplate (Get1Resource ('TIP ', id));\r\n\t\tFailNil (template);\r\n\r\n\t\tHNoPurge (Handle (template));\r\n\r\n\t\ttip.fSize := template^^.size;\r\n\t\ttip.fSpot := template^^.spot\r\n\r\n\t\tEND;\r\n\r\n\tpixels := tip.fSize.h * tip.fSize.v;\r\n\r\n\ttip.fMask := NewHandle (pixels);\r\n\tFailMemError;\r\n\r\n\tIF id = 0 THEN\r\n\t\tBlockMove (@gCustomTip, tip.fMask^, pixels)\r\n\tELSE\r\n\t\tBEGIN\r\n\t\tBlockMove (@template^^.data, tip.fMask^, pixels);\r\n\t\tHPurge (Handle (template))\r\n\t\tEND;\r\n\r\n\ttip.fMask2 := NewHandle (pixels);\r\n\tFailMemError;\r\n\r\n\ttip.fData [0] := NewHandle (pixels);\r\n\tFailMemError;\r\n\r\n\ttip.fData [1] := NewHandle (pixels);\r\n\tFailMemError;\r\n\r\n\tIF view.fChannel = kRGBChannels THEN\r\n\t\tBEGIN\r\n\r\n\t\ttip.fData [2] := NewHandle (pixels);\r\n\t\tFailMemError;\r\n\r\n\t\ttip.fData [3] := NewHandle (pixels);\r\n\t\tFailMemError;\r\n\r\n\t\tDoSetBytes (tip.fData [1]^, pixels, view.ForegroundByte (0));\r\n\t\tDoSetBytes (tip.fData [2]^, pixels, view.ForegroundByte (1));\r\n\t\tDoSetBytes (tip.fData [3]^, pixels, view.ForegroundByte (2))\r\n\r\n\t\tEND\r\n\r\n\tELSE\r\n\t\tBEGIN\r\n\r\n\t\ttip.fData [2] := NIL;\r\n\t\ttip.fData [3] := NIL;\r\n\r\n\t\tDoSetBytes (tip.fData [1]^, pixels, view.ForeGroundByte (0))\r\n\r\n\t\tEND;\r\n\r\n\tMoveHHi (tip.fMask);\r\n\tHLock (tip.fMask);\r\n\r\n\tMoveHHi (tip.fMask2);\r\n\tHLock (tip.fMask2);\r\n\r\n\tFOR band := 0 TO 3 DO\r\n\t\tIF tip.fData [band] &lt;&gt; NIL THEN\r\n\t\t\tBEGIN\r\n\t\t\tMoveHHi (tip.fData [band]);\r\n\t\t\tHLock (tip.fData [band])\r\n\t\t\tEND\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nFUNCTION TipCrossSection (tip: TTip): LONGINT;\r\n\r\n\tVAR\r\n\t\tr: INTEGER;\r\n\t\tc: INTEGER;\r\n\t\tsum: LONGINT;\r\n\t\trows: INTEGER;\r\n\t\tcols: INTEGER;\r\n\t\tmaxRow: LONGINT;\r\n\t\tmaxCol: LONGINT;\r\n\r\n\tBEGIN\r\n\r\n\trows := tip.fSize.v;\r\n\tcols := tip.fSize.h;\r\n\r\n\tmaxRow := 0;\r\n\r\n\tFOR r := 0 TO rows - 1 DO\r\n\t\tBEGIN\r\n\t\tsum := 0;\r\n\t\tFOR c := 0 TO cols - 1 DO\r\n\t\t\tsum := sum + BAND (Ptr (ORD4 (tip.fMask^) + r * cols + c)^, $FF);\r\n\t\tIF maxRow &lt; sum THEN maxRow := sum\r\n\t\tEND;\r\n\r\n\tmaxCol := 0;\r\n\r\n\tFOR c := 0 TO cols - 1 DO\r\n\t\tBEGIN\r\n\t\tsum := 0;\r\n\t\tFOR r := 0 TO rows - 1 DO\r\n\t\t\tsum := sum + BAND (Ptr (ORD4 (tip.fMask^) + r * cols + c)^, $FF);\r\n\t\tIF maxCol &lt; sum THEN maxCol := sum\r\n\t\tEND;\r\n\r\n\tTipCrossSection := Min (maxRow, maxCol)\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TMarkingTool.IMarkingTool (view: TImageView;\r\n\t\t\t\t\t\t\t\t\t itsCommand: INTEGER;\r\n\t\t\t\t\t\t\t\t\t cacheSize: Point;\r\n\t\t\t\t\t\t\t\t\t failMessage: LONGINT;\r\n\t\t\t\t\t\t\t\t\t needAlpha: BOOLEAN);\r\n\r\n\tVAR\r\n\t\tfi: FailInfo;\r\n\t\tchannel: INTEGER;\r\n\t\told: TMarkingTool;\r\n\t\tchannels: INTEGER;\r\n\t\taVMArray: TVMArray;\r\n\r\n\tPROCEDURE CleanUp (error: INTEGER; message: LONGINT);\r\n\t\tBEGIN\r\n\t\tFree\r\n\t\tEND;\r\n\r\n\tBEGIN\r\n\r\n\tfAlphaChannel := NIL;\r\n\r\n\tfChannel := view.fChannel;\r\n\r\n\tfMarkedArea := gZeroRect;\r\n\r\n\tfCachedArea := gZeroRect;\r\n\r\n\tfCacheSize := cacheSize;\r\n\r\n\tfUpperPage := -1;\r\n\tfLowerPage := -1;\r\n\r\n\tfLastPoint.h := -1;\r\n\tfLastPoint.v := -1;\r\n\r\n\tfAuxView   := NIL;\r\n\tfAuxCursor := FALSE;\r\n\r\n\tfFailMessage := failMessage;\r\n\r\n\tIBufferCommand (itsCommand, view);\r\n\r\n\tfViewConstrain := FALSE;\r\n\tfConstrainsMouse := TRUE;\r\n\r\n\tfPixelAlign := TRUE;\r\n\tfConstrainH := TRUE;\r\n\tfConstrainV := TRUE;\r\n\r\n\tCatchFailures (fi, CleanUp);\r\n\r\n\tIF MEMBER (gLastCommand, TMarkingTool) THEN\r\n\t\tIF gLastCommand.fChangedDocument = fDoc THEN\r\n\t\t\tBEGIN\r\n\r\n\t\t\told := TMarkingTool (gLastCommand);\r\n\r\n\t\t\tfLastPoint := old.fLastPoint;\r\n\r\n\t\t\tfBuffer [0] := old.fBuffer [0];\r\n\t\t\tfBuffer [1] := old.fBuffer [1];\r\n\t\t\tfBuffer [2] := old.fBuffer [2];\r\n\r\n\t\t\told.fBuffer [0] := NIL;\r\n\t\t\told.fBuffer [1] := NIL;\r\n\t\t\told.fBuffer [2] := NIL\r\n\r\n\t\t\tEND;\r\n\r\n\tgApplication.CommitLastCommand;\r\n\r\n\tfDoc.KillEffect (TRUE);\r\n\tfDoc.FreeFloat;\r\n\r\n\tIF fChannel = kRGBChannels THEN\r\n\t\tchannels := 3\r\n\tELSE\r\n\t\tchannels := 1;\r\n\r\n\tFOR channel := 0 TO 2 DO\r\n\r\n\t\tIF fBuffer [channel] &lt;&gt; NIL THEN\r\n\r\n\t\t\tIF channel &gt;= channels THEN\r\n\t\t\t\tBEGIN\r\n\t\t\t\tfBuffer [channel] . Free;\r\n\t\t\t\tfBuffer [channel] := NIL\r\n\t\t\t\tEND\r\n\r\n\t\t\tELSE\r\n\t\t\t\tfBuffer [channel] . Undefine\r\n\r\n\t\tELSE IF channel &lt; channels THEN\r\n\t\t\tBEGIN\r\n\t\t\taVMArray := NewVMArray (fDoc.fRows, fDoc.fCols, 1);\r\n\t\t\tfBuffer [channel] := aVMArray\r\n\t\t\tEND;\r\n\r\n\tfPhysicalSize := fBuffer [0] . fPhysicalSize;\r\n\r\n\tIF NOT EmptyRect (fDoc.fSelectionRect) OR needAlpha THEN\r\n\t\tBEGIN\r\n\r\n\t\taVMArray := NewVMArray (fDoc.fRows, fDoc.fCols, 1);\r\n\t\tfAlphaChannel := aVMArray;\r\n\r\n\t\tIF fDoc.fMode = IndexedColorMode THEN\r\n\t\t\tBEGIN\r\n\t\t\tDoSetBytes (@fAlphaMap [0  ], 128,\t \u06f0);\r\n\t\t\tDoSetBytes (@fAlphaMap [128], 128, 255)\r\n\t\t\tEND\r\n\t\tELSE\r\n\t\t\tfAlphaMap := gNullLUT\r\n\r\n\t\tEND;\r\n\r\n\tSuccess (fi)\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoCommand}\r\n\r\nPROCEDURE TMarkingTool.Free; OVERRIDE;\r\n\r\n\tBEGIN\r\n\r\n\tFreeObject (fAlphaChannel);\r\n\r\n\tINHERITED Free\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$IFC qTrace} {$D+} {$ENDC}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TMarkingTool.TrackFeedBack (anchorPoint: Point;\r\n\t\t\t\t\t\t\t\t\t  nextPoint: Point;\r\n\t\t\t\t\t\t\t\t\t  turnItOn: BOOLEAN;\r\n\t\t\t\t\t\t\t\t\t  mouseDidMove: BOOLEAN); OVERRIDE;\r\n\r\n\tBEGIN\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TMarkingTool.TrackConstrain (anchorPoint: Point;\r\n\t\t\t\t\t\t\t\t\t   previousPoint: Point;\r\n\t\t\t\t\t\t\t\t\t   VAR nextPoint: Point); OVERRIDE;\r\n\r\n\tVAR\r\n\t\tmag: INTEGER;\r\n\t\tdelta: Point;\r\n\t\toffset: INTEGER;\r\n\t\ttheKeys: KeyMap;\r\n\r\n\tBEGIN\r\n\r\n\tmag := fView.fMagnification;\r\n\r\n\tIF (mag &gt; 1) AND fPixelAlign THEN\r\n\t\tBEGIN\r\n\r\n\t\toffset := BSL (mag, 6);\r\n\r\n\t\tnextPoint.h := (nextPoint.h + offset) DIV mag * mag - offset;\r\n\t\tnextPoint.v := (nextPoint.v + offset) DIV mag * mag - offset;\r\n\r\n\t\tIF fConstrainH AND fConstrainV THEN\r\n\t\t\tBEGIN\r\n\t\t\tanchorPoint.h := (anchorPoint.h + offset) DIV mag * mag - offset;\r\n\t\t\tanchorPoint.v := (anchorPoint.v + offset) DIV mag * mag - offset\r\n\t\t\tEND\r\n\r\n\t\tEND;\r\n\r\n\tIF fConstrainH AND fConstrainV THEN\r\n\t\tBEGIN\r\n\r\n\t\tdelta.h := ABS (nextPoint.h - anchorPoint.h);\r\n\t\tdelta.v := ABS (nextPoint.v - anchorPoint.v);\r\n\r\n\t\tIF delta.h &gt; delta.v + gStdHysteresis.h THEN\r\n\t\t\tfConstrainH := FALSE\r\n\r\n\t\tELSE IF delta.v &gt; delta.h + gStdHysteresis.h THEN\r\n\t\t\tfConstrainV := FALSE\r\n\r\n\t\tEND;\r\n\r\n\tGetKeys (theKeys);\r\n\r\n\tIF theKeys [kShiftCode] THEN\r\n\t\tBEGIN\r\n\r\n\t\tIF fConstrainH THEN\r\n\t\t\tnextPoint.h := anchorPoint.h;\r\n\r\n\t\tIF fConstrainV THEN\r\n\t\t\tnextPoint.v := anchorPoint.v\r\n\r\n\t\tEND\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TMarkingTool.BuildAlpha (lower, upper: INTEGER);\r\n\r\n\tVAR\r\n\t\tr: Rect;\r\n\t\tsrcPtr: Ptr;\r\n\t\tdstPtr: Ptr;\r\n\t\tline: INTEGER;\r\n\r\n\tBEGIN\r\n\r\n\tIF fAlphaChannel &lt;&gt; NIL THEN\r\n\t\tBEGIN\r\n\r\n\t\tFOR line := lower TO upper DO\r\n\t\t\tBEGIN\r\n\r\n\t\t\tdstPtr := fAlphaChannel.NeedPtr (line, line, TRUE);\r\n\r\n\t\t\tDoSetBytes (dstPtr, fDoc.fCols, 0);\r\n\r\n\t\t\tr := fDoc.fSelectionRect;\r\n\r\n\t\t\tIF r.bottom = r.top THEN\r\n\t\t\t\tBEGIN\r\n\t\t\t\tr.top\t := \u06f0;\r\n\t\t\t\tr.left\t := \u06f0;\r\n\t\t\t\tr.bottom := fDoc.fRows;\r\n\t\t\t\tr.right  := fDoc.fCols\r\n\t\t\t\tEND;\r\n\r\n\t\t\tIF (line &gt;= r.top) AND (line &lt; r.bottom) THEN\r\n\t\t\t\tBEGIN\r\n\r\n\t\t\t\tdstPtr := Ptr (ORD4 (dstPtr) + r.left);\r\n\r\n\t\t\t\tIF fDoc.fSelectionMask = NIL THEN\r\n\t\t\t\t\tDoSetBytes (dstPtr,\r\n\t\t\t\t\t\t\t\tr.right - r.left,\r\n\t\t\t\t\t\t\t\tORD (fAlphaMap [255]))\r\n\r\n\t\t\t\tELSE\r\n\t\t\t\t\tBEGIN\r\n\r\n\t\t\t\t\tsrcPtr := fDoc.fSelectionMask.NeedPtr (line - r.top,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t   line - r.top,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t   FALSE);\r\n\r\n\t\t\t\t\tBlockMove (srcPtr, dstPtr, r.right - r.left);\r\n\r\n\t\t\t\t\tfDoc.fSelectionMask.DoneWithPtr;\r\n\r\n\t\t\t\t\tDoMapBytes (dstPtr, r.right - r.left, fAlphaMap)\r\n\r\n\t\t\t\t\tEND\r\n\r\n\t\t\t\tEND;\r\n\r\n\t\t\tfAlphaChannel.DoneWithPtr\r\n\r\n\t\t\tEND;\r\n\r\n\t\tIF fDoc.fSelectionMask &lt;&gt; NIL THEN\r\n\t\t\tfDoc.fSelectionMask.Flush\r\n\r\n\t\tEND\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TMarkingTool.SaveLines (lower, upper: INTEGER);\r\n\r\n\tVAR\r\n\t\tr: Rect;\r\n\t\tsrcPtr: Ptr;\r\n\t\tdstPtr: Ptr;\r\n\t\tpage: INTEGER;\r\n\t\tline: INTEGER;\r\n\t\tchannel: INTEGER;\r\n\t\tlowerPage: INTEGER;\r\n\t\tupperPage: INTEGER;\r\n\t\tblocksPerPage: INTEGER;\r\n\r\n\tBEGIN\r\n\r\n\tblocksPerPage := fBuffer [0] . fBlocksPerPage;\r\n\r\n\tlowerPage := lower DIV blocksPerPage;\r\n\tupperPage := upper DIV blocksPerPage;\r\n\r\n\tIF (lowerPage &gt;= fLowerPage) &amp; (upperPage &lt;= fUpperPage) THEN\r\n\t\tEXIT (SaveLines);\r\n\r\n\tIF (fUpperPage = -1) OR (lowerPage &lt; fLowerPage) AND\r\n\t\t\t\t\t\t\t(upperPage &gt; fUpperPage) THEN\r\n\t\tBEGIN\r\n\t\tfLowerPage := lowerPage;\r\n\t\tfUpperPage := upperPage\r\n\t\tEND\r\n\r\n\tELSE IF lowerPage &lt; fLowerPage THEN\r\n\t\tBEGIN\r\n\t\tupperPage  := fLowerPage - 1;\r\n\t\tfLowerPage := lowerPage\r\n\t\tEND\r\n\r\n\tELSE\r\n\t\tBEGIN\r\n\t\tlowerPage  := fUpperPage + 1;\r\n\t\tfUpperPage := upperPage\r\n\t\tEND;\r\n\r\n\tIF fChannel = kRGBChannels THEN\r\n\r\n\t\tFOR channel := 0 TO 2 DO\r\n\t\t\tBEGIN\r\n\r\n\t\t\tFOR page := lowerPage TO upperPage DO\r\n\t\t\t\tBEGIN\r\n\r\n\t\t\t\tline := page * blocksPerPage;\r\n\r\n\t\t\t\tdstPtr := fBuffer [channel] . NeedPtr (line, line, TRUE);\r\n\t\t\t\tsrcPtr := fDoc.fData [channel] . NeedPtr (line, line, FALSE);\r\n\r\n\t\t\t\tBlockMove (srcPtr, dstPtr, kVMPageSize);\r\n\r\n\t\t\t\tfDoc.fData [channel] . DoneWithPtr;\r\n\t\t\t\tfBuffer [channel] . DoneWithPtr\r\n\r\n\t\t\t\tEND;\r\n\r\n\t\t\tfDoc.fData [channel] . Flush;\r\n\t\t\tfBuffer [channel] . Flush\r\n\r\n\t\t\tEND\r\n\r\n\tELSE\r\n\t\tBEGIN\r\n\r\n\t\tFOR page := lowerPage TO upperPage DO\r\n\t\t\tBEGIN\r\n\r\n\t\t\tline := page * blocksPerPage;\r\n\r\n\t\t\tdstPtr := fBuffer [0] . NeedPtr (line, line, TRUE);\r\n\t\t\tsrcPtr := fDoc.fData [fChannel] . NeedPtr (line, line, FALSE);\r\n\r\n\t\t\tBlockMove (srcPtr, dstPtr, kVMPageSize);\r\n\r\n\t\t\tfDoc.fData [fChannel] . DoneWithPtr;\r\n\t\t\tfBuffer [0] . DoneWithPtr\r\n\r\n\t\t\tEND;\r\n\r\n\t\tfDoc.fData [fChannel] . Flush;\r\n\t\tfBuffer [0] . Flush\r\n\r\n\t\tEND\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TMarkingTool.AddToMarked (r: Rect);\r\n\r\n\tVAR\r\n\t\tarea: Rect;\r\n\r\n\tBEGIN\r\n\r\n\tarea := fMarkedArea;\r\n\r\n\tIF area.bottom = 0 THEN\r\n\t\tBEGIN\r\n\t\tBuildAlpha (r.top, r.bottom - 1);\r\n\t\tSaveLines  (r.top, r.bottom - 1);\r\n\t\tarea := r\r\n\t\tEND\r\n\r\n\tELSE\r\n\t\tBEGIN\r\n\r\n\t\tIF r.left  &lt; area.left\tTHEN area.left\t:= r.left;\r\n\t\tIF r.right &gt; area.right THEN area.right := r.right;\r\n\r\n\t\tIF r.top &lt; area.top THEN\r\n\t\t\tBEGIN\r\n\t\t\tBuildAlpha (r.top, area.top - 1);\r\n\t\t\tSaveLines  (r.top, area.top - 1);\r\n\t\t\tarea.top := r.top\r\n\t\t\tEND;\r\n\r\n\t\tIF r.bottom &gt; area.bottom THEN\r\n\t\t\tBEGIN\r\n\t\t\tBuildAlpha (area.bottom, r.bottom - 1);\r\n\t\t\tSaveLines  (area.bottom, r.bottom - 1);\r\n\t\t\tarea.bottom := r.bottom\r\n\t\t\tEND\r\n\r\n\t\tEND;\r\n\r\n\tfMarkedArea := area\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TMarkingTool.DrawAuxCursor (pt: Point);\r\n\r\n\tVAR\r\n\t\tsavePort: GrafPtr;\r\n\r\n\tBEGIN\r\n\r\n\tIF fAuxView &lt;&gt; fView THEN\r\n\t\tBEGIN\r\n\t\tGetPort (savePort);\r\n\t\tfAuxView.fFrame.Focus\r\n\t\tEND;\r\n\r\n\tPenNormal;\r\n\tPenMode (patXor);\r\n\r\n\tMoveTo (pt.h - 7, pt.v);\r\n\r\n\tLine (14,  0);\r\n\tMove (-7, -7);\r\n\tLine ( 0, 14);\r\n\r\n\tfAuxCursor\t := NOT fAuxCursor;\r\n\tfAuxLocation := pt;\r\n\r\n\tIF fAuxView &lt;&gt; fView THEN\r\n\t\tSetPort (savePort)\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TMarkingTool.FlushCache;\r\n\r\n\tVAR\r\n\t\tr: Rect;\r\n\t\trr: Rect;\r\n\t\thideAux: BOOLEAN;\r\n\r\n\tBEGIN\r\n\r\n\tr := fCachedArea;\r\n\r\n\tIF r.bottom &lt;&gt; 0 THEN\r\n\t\tBEGIN\r\n\r\n\t\thideAux := FALSE;\r\n\r\n\t\tIF (fAuxView = fView) &amp; fAuxCursor THEN\r\n\t\t\tBEGIN\r\n\r\n\t\t\trr.topLeft\t:= fAuxLocation;\r\n\t\t\trr.botRight := fAuxLocation;\r\n\r\n\t\t\tInsetRect (rr, -8, -8);\r\n\r\n\t\t\tIF SectRect (r, rr, rr) THEN\r\n\t\t\t\tBEGIN\r\n\t\t\t\thideAux := TRUE;\r\n\t\t\t\tDrawAuxCursor (fAuxLocation)\r\n\t\t\t\tEND\r\n\r\n\t\t\tEND;\r\n\r\n\t\tfView.DrawNow (r, FALSE);\r\n\r\n\t\tIF hideAux THEN\r\n\t\t\tDrawAuxCursor (fAuxLocation);\r\n\r\n\t\tfCachedArea := gZeroRect\r\n\r\n\t\tEND\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TMarkingTool.AddToCache (r: Rect);\r\n\r\n\tVAR\r\n\t\tvr: Rect;\r\n\t\tarea: Rect;\r\n\t\tmag: INTEGER;\r\n\r\n\tBEGIN\r\n\r\n\tvr := r;\r\n\r\n\tmag := fView.fMagnification;\r\n\r\n\tIF mag &gt; 1 THEN\r\n\t\tBEGIN\r\n\t\tvr.top\t  := vr.top    * mag;\r\n\t\tvr.left   := vr.left   * mag;\r\n\t\tvr.bottom := vr.bottom * mag;\r\n\t\tvr.right  := vr.right  * mag\r\n\t\tEND\r\n\r\n\tELSE IF mag &lt; 1 THEN\r\n\t\tBEGIN\r\n\t\tmag := -mag;\r\n\t\tvr.top\t  := (vr.top\t+ mag - 1) DIV mag;\r\n\t\tvr.left   := (vr.left\t+ mag - 1) DIV mag;\r\n\t\tvr.bottom := (vr.bottom + mag - 1) DIV mag;\r\n\t\tvr.right  := (vr.right\t+ mag - 1) DIV mag\r\n\t\tEND;\r\n\r\n\tIF (vr.bottom &gt; vr.top) AND (vr.right &gt; vr.left) THEN\r\n\t\tBEGIN\r\n\r\n\t\tarea := fCachedArea;\r\n\r\n\t\tIF area.bottom = 0 THEN\r\n\t\t\tfCachedArea := vr\r\n\r\n\t\tELSE\r\n\t\t\tBEGIN\r\n\r\n\t\t\tIF vr.top\t &lt; area.top    THEN area.top\t:= vr.top;\r\n\t\t\tIF vr.left\t &lt; area.left   THEN area.left\t:= vr.left;\r\n\t\t\tIF vr.bottom &gt; area.bottom THEN area.bottom := vr.bottom;\r\n\t\t\tIF vr.right  &gt; area.right  THEN area.right\t:= vr.right;\r\n\r\n\t\t\tIF (area.bottom - area.top &lt;= fCacheSize.v) AND\r\n\t\t\t   (area.right - area.left &lt;= fCacheSize.h) THEN\r\n\t\t\t\tfCachedArea := area\r\n\r\n\t\t\tELSE\r\n\t\t\t\tBEGIN\r\n\t\t\t\tFlushCache;\r\n\t\t\t\tfCachedArea := vr\r\n\t\t\t\tEND\r\n\r\n\t\t\tEND\r\n\r\n\t\tEND\r\n\r\n\tEND;\r\n\r\n{$IFC qTrace} {$D++} {$ENDC}\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TMarkingTool.FixReleasePoint (anchorPoint: Point;\r\n\t\t\t\t\t\t\t\t\t\tVAR nextPoint: Point);\r\n\r\n\tVAR\r\n\t\tpeekEvent: EventRecord;\r\n\r\n\tBEGIN\r\n\r\n\tIF EventAvail (mUpMask, peekEvent) THEN\r\n\t\tBEGIN\r\n\r\n\t\tnextPoint := peekEvent.where;\r\n\r\n\t\tGlobalToLocal (nextPoint);\r\n\r\n\t\tIF fConstrainsMouse THEN\r\n\t\t\tTrackConstrain (anchorPoint, nextPoint, nextPoint)\r\n\r\n\t\tEND;\r\n\r\n\tIF PtInRect (nextPoint, fView.fExtentRect) THEN\r\n\t\tBEGIN\r\n\r\n\t\tfLastPoint := nextPoint;\r\n\r\n\t\t{$H-}\r\n\t\tfView.CvtView2Image (fLastPoint)\r\n\t\t{$H+}\r\n\r\n\t\tEND\r\n\r\n\tELSE\r\n\t\tBEGIN\r\n\t\tfLastPoint.h := -1;\r\n\t\tfLastPoint.v := -1\r\n\t\tEND\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TMarkingTool.SwapRect (r: Rect; iArray, bArray: TVMArray);\r\n\r\n\tVAR\r\n\t\tiPtr: Ptr;\r\n\t\tbPtr: Ptr;\r\n\t\tfi: FailInfo;\r\n\t\trow: INTEGER;\r\n\r\n\tPROCEDURE CleanUp (error: INTEGER; message: LONGINT);\r\n\t\tBEGIN\r\n\r\n\t\tIF iPtr &lt;&gt; NIL THEN iArray.DoneWithPtr;\r\n\t\tIF bPtr &lt;&gt; NIL THEN bArray.DoneWithPtr;\r\n\r\n\t\tiArray.Flush;\r\n\t\tbArray.Flush\r\n\r\n\t\tEND;\r\n\r\n\tBEGIN\r\n\r\n\tCatchFailures (fi, CleanUp);\r\n\r\n\tFOR row := r.top TO r.bottom - 1 DO\r\n\t\tBEGIN\r\n\r\n\t\tiPtr := NIL;\r\n\t\tbPtr := NIL;\r\n\r\n\t\tiPtr := Ptr (ORD4 (iArray.NeedPtr (row, row, TRUE)) + r.left);\r\n\t\tbPtr := Ptr (ORD4 (bArray.NeedPtr (row, row, TRUE)) + r.left);\r\n\r\n\t\tDoSwapBytes (iPtr, bPtr, r.right - r.left);\r\n\r\n\t\tiArray.DoneWithPtr;\r\n\t\tbArray.DoneWithPtr\r\n\r\n\t\tEND;\r\n\r\n\tiArray.Flush;\r\n\tbArray.Flush;\r\n\r\n\tSuccess (fi)\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TMarkingTool.SwapMarkedArea;\r\n\r\n\tVAR\r\n\t\tr: Rect;\r\n\r\n\tBEGIN\r\n\r\n\tr := fMarkedArea;\r\n\r\n\tIF NOT EmptyRect (r) THEN\r\n\t\tIF fChannel = kRGBChannels THEN\r\n\t\t\tBEGIN\r\n\t\t\tSwapRect (r, fDoc.fData [0], fBuffer [0]);\r\n\t\t\tSwapRect (r, fDoc.fData [1], fBuffer [1]);\r\n\t\t\tSwapRect (r, fDoc.fData [2], fBuffer [2])\r\n\t\t\tEND\r\n\t\tELSE\r\n\t\t\tSwapRect (r, fDoc.fData [fChannel], fBuffer [0])\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TMarkingTool.FlushImage;\r\n\r\n\tVAR\r\n\t\tband: INTEGER;\r\n\r\n\tBEGIN\r\n\r\n\tFOR band := 0 TO kMaxChannels - 1 DO\r\n\t\tBEGIN\r\n\r\n\t\tIF fDoc.fData [band] &lt;&gt; NIL THEN\r\n\t\t\tfDoc.fData [band] . Flush;\r\n\r\n\t\tIF fDoc.fMagicData [band] &lt;&gt; NIL THEN\r\n\t\t\tfDoc.fMagicData [band] . Flush;\r\n\r\n\t\tIF gCloneDoc &lt;&gt; NIL THEN\r\n\t\t\tIF gCloneDoc.fData [band] &lt;&gt; NIL THEN\r\n\t\t\t\tgCloneDoc.fData [band] . Flush\r\n\r\n\t\tEND;\r\n\r\n\tFOR band := 0 TO 3 DO\r\n\t\tIF gPattern [band] &lt;&gt; NIL THEN\r\n\t\t\tgPattern [band] . Flush\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TMarkingTool.RecoverFailure;\r\n\r\n\tVAR\r\n\t\tr: Rect;\r\n\t\tfi: FailInfo;\r\n\r\n\tPROCEDURE CleanUp (error: INTEGER; message: LONGINT);\r\n\t\tBEGIN\r\n\t\tEXIT (RecoverFailure)\r\n\t\tEND;\r\n\r\n\tBEGIN\r\n\r\n\tCatchFailures (fi, CleanUp);\r\n\r\n\tIF fAuxCursor THEN\r\n\t\tDrawAuxCursor (fAuxLocation);\r\n\r\n\tIF NOT EmptyRect (fMarkedArea) THEN\r\n\t\tBEGIN\r\n\r\n\t\tMoveHands (FALSE);\r\n\r\n\t\tSwapMarkedArea;\r\n\r\n\t\tr := fMarkedArea;\r\n\r\n\t\tfView.UpdateImageArea (r, FALSE)\r\n\r\n\t\tEND;\r\n\r\n\tSuccess (fi)\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TMarkingTool.DoIt; OVERRIDE;\r\n\r\n\tVAR\r\n\t\tr: Rect;\r\n\r\n\tBEGIN\r\n\r\n\tIF fAlphaChannel &lt;&gt; NIL THEN\r\n\t\tBEGIN\r\n\t\tfAlphaChannel.Free;\r\n\t\tfAlphaChannel := NIL\r\n\t\tEND;\r\n\r\n\tIF NOT EmptyRect (fDoc.fSelectionRect) THEN\r\n\t\tfView.DoHighlightSelection (HLOff, HLOn);\r\n\r\n\tfView.DoDrawExtraFeedback (fView.fExtentRect);\r\n\r\n\tIF fDoc.fViewList.fSize &gt; 1 THEN\r\n\t\tBEGIN\r\n\r\n\t\tr := fMarkedArea;\r\n\r\n\t\tfDoc.UpdateImageArea (r, FALSE, FALSE, fChannel)\r\n\r\n\t\tEND\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TMarkingTool.UndoIt; OVERRIDE;\r\n\r\n\tVAR\r\n\t\tr: Rect;\r\n\r\n\tBEGIN\r\n\r\n\tMoveHands (FALSE);\r\n\r\n\tSwapMarkedArea;\r\n\r\n\tr := fMarkedArea;\r\n\r\n\tfDoc.UpdateImageArea (r, TRUE, TRUE, fChannel)\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TMarkingTool.RedoIt; OVERRIDE;\r\n\r\n\tBEGIN\r\n\tUndoIt\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TEraserTool.IEraserTool (view: TImageView; magic: BOOLEAN);\r\n\r\n\tVAR\r\n\t\tcacheSize: Point;\r\n\r\n\tBEGIN\r\n\r\n\tfMagic := magic;\r\n\r\n\tcacheSize.h := 32;\r\n\tcacheSize.v := 32;\r\n\r\n\tIMarkingTool (view, cErasing, cacheSize, msgCannotErase, FALSE);\r\n\r\n\tfPixelAlign := FALSE;\r\n\r\n\tIF fChannel = kRGBChannels THEN\r\n\t\tBEGIN\r\n\t\tfColor1 := view.BackGroundByte (0);\r\n\t\tfColor2 := view.BackGroundByte (1);\r\n\t\tfColor3 := view.BackGroundByte (2)\r\n\t\tEND\r\n\tELSE\r\n\t\tfColor1 := view.BackGroundByte (fChannel)\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$IFC qTrace} {$D+} {$ENDC}\r\n\r\n{$S ADoDraw}\r\n\r\nFUNCTION TEraserTool.TrackMouse (aTrackPhase: TrackPhase;\r\n\t\t\t\t\t\t\t\t VAR anchorPoint: Point;\r\n\t\t\t\t\t\t\t\t VAR previousPoint: Point;\r\n\t\t\t\t\t\t\t\t VAR nextPoint: Point;\r\n\t\t\t\t\t\t\t\t mouseDidMove: BOOLEAN): TCommand; OVERRIDE;\r\n\r\n\tVAR\r\n\t\tfi: FailInfo;\r\n\t\tmag: INTEGER;\r\n\t\tstartPt: Point;\r\n\t\tlastRect: Rect;\r\n\t\tblocksPerPage: INTEGER;\r\n\r\n\tPROCEDURE CleanUp (error: INTEGER; message: LONGINT);\r\n\r\n\t\tBEGIN\r\n\t\tRecoverFailure;\r\n\t\tFlushImage;\r\n\t\tmessage := fFailMessage;\r\n\t\tFree;\r\n\t\tFailure (error, message)\r\n\t\tEND;\r\n\r\n\tPROCEDURE EraseRect (r: Rect;\r\n\t\t\t\t\t\t band: INTEGER;\r\n\t\t\t\t\t\t color: INTEGER;\r\n\t\t\t\t\t\t update: BOOLEAN);\r\n\r\n\t\tVAR\r\n\t\t\tdstPtr: Ptr;\r\n\t\t\tsrcPtr: Ptr;\r\n\t\t\tfi: FailInfo;\r\n\t\t\talphaPtr: Ptr;\r\n\t\t\trows: INTEGER;\r\n\t\t\tcols: INTEGER;\r\n\r\n\t\tPROCEDURE CleanUp (error: INTEGER; message: LONGINT);\r\n\t\t\tBEGIN\r\n\t\t\tfDoc.fData [band] . DoneWithPtr;\r\n\t\t\tIF srcPtr &lt;&gt; NIL THEN\r\n\t\t\t\tfDoc.fMagicData [band] . DoneWithPtr\r\n\t\t\tEND;\r\n\r\n\t\tBEGIN\r\n\r\n\t\tsrcPtr := NIL;\r\n\r\n\t\tdstPtr := fDoc.fData [band] . NeedPtr (r.top,\r\n\t\t\t\t\t\t\t\t\t\t\t   r.bottom - 1,\r\n\t\t\t\t\t\t\t\t\t\t\t   TRUE);\r\n\t\tdstPtr := Ptr (ORD4 (dstPtr) + r.left);\r\n\r\n\t\tCatchFailures (fi, CleanUp);\r\n\r\n\t\tIF fMagic THEN\r\n\t\t\tBEGIN\r\n\t\t\tsrcPtr := fDoc.fMagicData [band] . NeedPtr (r.top,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tr.bottom - 1,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tFALSE);\r\n\t\t\tsrcPtr := Ptr (ORD4 (srcPtr) + r.left)\r\n\t\t\tEND;\r\n\r\n\t\trows := r.bottom - r.top;\r\n\t\tcols := r.right - r.left;\r\n\r\n\t\tIF fAlphaChannel = NIL THEN\r\n\t\t\tIF fMagic THEN\r\n\t\t\t\tDoMagicRect (srcPtr, dstPtr, fPhysicalSize, rows, cols)\r\n\t\t\tELSE\r\n\t\t\t\tDoEraseRect (dstPtr, fPhysicalSize, rows, cols, color)\r\n\r\n\t\tELSE\r\n\t\t\tBEGIN\r\n\r\n\t\t\talphaPtr := fAlphaChannel.NeedPtr (r.top, r.bottom - 1, update);\r\n\t\t\talphaPtr := Ptr (ORD4 (alphaPtr) + r.left);\r\n\r\n\t\t\tIF fMagic THEN\r\n\t\t\t\tDoAlphaMagicRect (srcPtr, dstPtr, alphaPtr,\r\n\t\t\t\t\t\t\t\t  fPhysicalSize, rows, cols)\r\n\t\t\tELSE\r\n\t\t\t\tDoAlphaEraseRect (dstPtr, alphaPtr,\r\n\t\t\t\t\t\t\t\t  fPhysicalSize, rows, cols, color);\r\n\r\n\t\t\tIF update THEN\r\n\t\t\t\tDoEraseRect (alphaPtr, fPhysicalSize, rows, cols, 0);\r\n\r\n\t\t\tfAlphaChannel.DoneWithPtr\r\n\r\n\t\t\tEND;\r\n\r\n\t\tSuccess (fi);\r\n\r\n\t\tCleanUp (0, 0)\r\n\r\n\t\tEND;\r\n\r\n\tPROCEDURE UpdateRect (r: Rect);\r\n\r\n\t\tVAR\r\n\t\t\trr: Rect;\r\n\r\n\t\tBEGIN\r\n\r\n\t\tIF (r.right &gt; r.left) AND (r.bottom &gt; r.top) THEN\r\n\t\t\tBEGIN\r\n\r\n\t\t\tAddToMarked (r);\r\n\r\n\t\t\trr := r;\r\n\r\n\t\t\t\tREPEAT\r\n\r\n\t\t\t\trr.bottom := Min ((rr.top DIV blocksPerPage + 1) *\r\n\t\t\t\t\t\t\t\t  blocksPerPage, r.bottom);\r\n\r\n\t\t\t\tIF fChannel = kRGBChannels THEN\r\n\t\t\t\t\tBEGIN\r\n\t\t\t\t\tEraseRect (rr, 0, fColor1, FALSE);\r\n\t\t\t\t\tEraseRect (rr, 1, fColor2, FALSE);\r\n\t\t\t\t\tEraseRect (rr, 2, fColor3, TRUE)\r\n\t\t\t\t\tEND\r\n\t\t\t\tELSE\r\n\t\t\t\t\tEraseRect (rr, fChannel, fColor1, TRUE);\r\n\r\n\t\t\t\trr.top := rr.bottom\r\n\r\n\t\t\t\tUNTIL rr.top = r.bottom;\r\n\r\n\t\t\tAddToCache (r)\r\n\r\n\t\t\tEND\r\n\r\n\t\tEND;\r\n\r\n\tPROCEDURE ErasePoint (pt: Point);\r\n\r\n\t\tVAR\r\n\t\t\tr: Rect;\r\n\t\t\trr: Rect;\r\n\t\t\trrr: Rect;\r\n\t\t\thalf: INTEGER;\r\n\t\t\trows: INTEGER;\r\n\t\t\tcols: INTEGER;\r\n\r\n\t\tBEGIN\r\n\r\n\t\tr.top\t := pt.v - 8;\r\n\t\tr.left\t := pt.h - 8;\r\n\t\tr.bottom := pt.v + 8;\r\n\t\tr.right  := pt.h + 8;\r\n\r\n\t\tIF mag &gt; 1 THEN\r\n\t\t\tBEGIN\r\n\t\t\thalf := BSR (mag, 1);\r\n\t\t\tr.top\t := (r.top\t  + half) DIV mag;\r\n\t\t\tr.left\t := (r.left   + half) DIV mag;\r\n\t\t\tr.bottom := (r.bottom + half) DIV mag;\r\n\t\t\tr.right  := (r.right  + half) DIV mag\r\n\t\t\tEND\r\n\r\n\t\tELSE IF mag &lt; 1 THEN\r\n\t\t\tBEGIN\r\n\t\t\tr.top\t := r.top\t * (-mag);\r\n\t\t\tr.left\t := r.left\t * (-mag);\r\n\t\t\tr.bottom := r.bottom * (-mag);\r\n\t\t\tr.right  := r.right  * (-mag)\r\n\t\t\tEND;\r\n\r\n\t\trows := fDoc.fRows;\r\n\t\tcols := fDoc.fCols;\r\n\r\n\t\tIF r.top\t&lt; 0    THEN r.top\t := \u06f0;\r\n\t\tIF r.left\t&lt; 0    THEN r.left\t := \u06f0;\r\n\t\tIF r.bottom &gt; rows THEN r.bottom := rows;\r\n\t\tIF r.right\t&gt; cols THEN r.right  := cols;\r\n\r\n\t\tIF (r.left\t &gt;= lastRect.right ) |\r\n\t\t   (r.top\t &gt;= lastRect.bottom) |\r\n\t\t   (r.right  &lt;= lastRect.left  ) |\r\n\t\t   (r.bottom &lt;= lastRect.top   ) THEN\r\n\t\t\tBEGIN\r\n\r\n\t\t\tUpdateRect (r);\r\n\r\n\t\t\tlastRect := r\r\n\r\n\t\t\tEND\r\n\r\n\t\tELSE\r\n\t\t\tBEGIN\r\n\r\n\t\t\trrr := r;\r\n\r\n\t\t\tIF r.top &lt; lastRect.top THEN\r\n\t\t\t\tBEGIN\r\n\r\n\t\t\t\trr := r;\r\n\t\t\t\trr.bottom := lastRect.top;\r\n\r\n\t\t\t\tUpdateRect (rr);\r\n\r\n\t\t\t\tr.top := lastRect.top\r\n\r\n\t\t\t\tEND;\r\n\r\n\t\t\tIF r.bottom &gt; lastRect.bottom THEN\r\n\t\t\t\tBEGIN\r\n\r\n\t\t\t\trr := r;\r\n\t\t\t\trr.top := lastRect.bottom;\r\n\r\n\t\t\t\tUpdateRect (rr);\r\n\r\n\t\t\t\tr.bottom := lastRect.bottom\r\n\r\n\t\t\t\tEND;\r\n\r\n\t\t\tIF r.left &lt; lastRect.left THEN\r\n\t\t\t\tBEGIN\r\n\r\n\t\t\t\trr := r;\r\n\t\t\t\trr.right := lastRect.left;\r\n\r\n\t\t\t\tUpdateRect (rr)\r\n\r\n\t\t\t\tEND;\r\n\r\n\t\t\tIF r.right &gt; lastRect.right THEN\r\n\t\t\t\tBEGIN\r\n\r\n\t\t\t\trr := r;\r\n\t\t\t\tr.left := lastRect.right;\r\n\r\n\t\t\t\tUpdateRect (rr)\r\n\r\n\t\t\t\tEND;\r\n\r\n\t\t\tlastRect := rrr\r\n\r\n\t\t\tEND\r\n\r\n\t\tEND;\r\n\r\n\tBEGIN\r\n\r\n\tTrackMouse := SELF;\r\n\r\n\tfView.TrackRulers;\r\n\r\n\tstartPt := previousPoint;\r\n\r\n\tIF aTrackPhase = TrackPress THEN\r\n\t\tBEGIN\r\n\r\n\t\tIF gEventInfo.theShiftKey AND (fLastPoint.h &gt;= 0) THEN\r\n\t\t\tBEGIN\r\n\t\t\tstartPt := fLastPoint;\r\n\t\t\tfView.CvtImage2View (startPt, kRoundDown)\r\n\t\t\tEND\r\n\r\n\t\tEND\r\n\r\n\tELSE IF aTrackPhase = TrackRelease THEN\r\n\t\tFixReleasePoint (anchorPoint, nextPoint);\r\n\r\n\tIF mouseDidMove THEN\r\n\t\tBEGIN\r\n\r\n\t\tCatchFailures (fi, CleanUp);\r\n\r\n\t\tmag := fView.fMagnification;\r\n\r\n\t\tblocksPerPage := fBuffer [0] . fBlocksPerPage;\r\n\r\n\t\tlastRect := gZeroRect;\r\n\r\n\t\tInterpolatePoints (startPt, nextPoint, ErasePoint);\r\n\r\n\t\tFlushCache;\r\n\r\n\t\tSuccess (fi)\r\n\r\n\t\tEND;\r\n\r\n\tIF aTrackPhase = TrackRelease THEN FlushImage\r\n\r\n\tEND;\r\n\r\n{$IFC qTrace} {$D++} {$ENDC}\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE FailBadMode (view: TImageView;\r\n\t\t\t\t\t   soft: BOOLEAN;\r\n\t\t\t\t\t   mode: TDrawingMode);\r\n\r\n\tVAR\r\n\t\tdoc: TImageDocument;\r\n\r\n\tBEGIN\r\n\r\n\tdoc := TImageDocument (view.fDocument);\r\n\r\n\tIF doc.fMode = HalftoneMode THEN\r\n\t\tFailure (errNoHalftone, 0);\r\n\r\n\tIF doc.fMode = IndexedColorMode THEN\r\n\t\tIF soft THEN\r\n\t\t\tFailure (errNoIndexedColor, 0)\r\n\t\tELSE IF mode = DarkenOnly THEN\r\n\t\t\tFailure (errNoDarkenOnly, 0)\r\n\t\tELSE IF mode = LightenOnly THEN\r\n\t\t\tFailure (errNoLightenOnly, 0);\r\n\r\n\tIF view.fChannel &lt;&gt; kRGBChannels THEN\r\n\t\tIF mode = ColorOnly THEN\r\n\t\t\tFailure (errNoColorOnly, 0)\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE GetMagicData (view: TImageView; tool: TTool; needChange: BOOLEAN);\r\n\r\n\tVAR\r\n\t\terr: OSErr;\r\n\t\tfi: FailInfo;\r\n\t\tchannel: INTEGER;\r\n\t\tanAppFile: AppFile;\r\n\t\tdoc: TImageDocument;\r\n\t\ttemp: TImageDocument;\r\n\r\n\tPROCEDURE CleanUp (error: INTEGER; message: LONGINT);\r\n\t\tBEGIN\r\n\t\ttemp.fRevertInfo := NIL;\r\n\t\ttemp.Free\r\n\t\tEND;\r\n\r\n\tBEGIN\r\n\r\n\tdoc := TImageDocument (view.fDocument);\r\n\r\n\tIF NOT doc.CanRevert THEN\r\n\t\tIF doc.fSaveExists OR doc.fImported THEN\r\n\t\t\tBEGIN\r\n\t\t\tIF needChange THEN Failure (errNoChangeSince, 0)\r\n\t\t\tEND\r\n\t\tELSE\r\n\t\t\tFailure (errNeverSaved, 0);\r\n\r\n\tIF doc.fMode &lt;&gt; doc.fMagicMode THEN\r\n\t\tFailure (errModeChanged, 0);\r\n\r\n\tIF (doc.fRows &lt;&gt; doc.fMagicRows) OR\r\n\t   (doc.fCols &lt;&gt; doc.fMagicCols) THEN\r\n\t\tFailure (errSizeChanged, 0);\r\n\r\n\tIF view.fChannel &gt;= doc.fMagicChannels THEN\r\n\t\tFailure (errNewChannel, 0);\r\n\r\n\tIF doc.fMagicData [0] &lt;&gt; NIL THEN\r\n\t\tEXIT (GetMagicData);\r\n\r\n\tMoveHands (TRUE);\r\n\r\n\ttemp := TImageDocument (gApplication.DoMakeDocument (cMouseCommand));\r\n\r\n\tCatchFailures (fi, CleanUp);\r\n\r\n\ttemp.fTitle \t := doc.fTitle;\r\n\ttemp.fFileType\t := doc.fFileType;\r\n\ttemp.fCreator\t := doc.fCreator;\r\n\ttemp.fVolRefNum  := doc.fVolRefNum;\r\n\ttemp.fModDate\t := doc.fModDate;\r\n\ttemp.fSaveExists := TRUE;\r\n\r\n\ttemp.fFormatCode := doc.fFormatCode;\r\n\ttemp.fRevertInfo := doc.fRevertInfo;\r\n\r\n\terr := temp.DiskFileChanged (TRUE);\r\n\r\n\tIF err &lt;&gt; noErr THEN Failure (errFileModified, 0);\r\n\r\n\tanAppFile.fName := '';\r\n\r\n\tgFormatCode := doc.fFormatCode;\r\n\r\n\ttemp.ReadFromFile (anAppFile, kForDisplay);\r\n\r\n\tIF (doc.fMagicRows &lt;&gt; temp.fRows) OR\r\n\t   (doc.fMagicCols &lt;&gt; temp.fCols) OR\r\n\t   (doc.fMagicMode &lt;&gt; temp.fMode) OR\r\n\t   (doc.fMagicChannels &lt;&gt; temp.fChannels) THEN\r\n\t\tFailure (errFileModified, 0);\r\n\r\n\tFOR channel := 0 TO temp.fChannels - 1 DO\r\n\t\tBEGIN\r\n\t\tdoc.fMagicData [channel] := temp.fData [channel];\r\n\t\ttemp.fData [channel] := NIL\r\n\t\tEND;\r\n\r\n\tSuccess (fi);\r\n\r\n\tCleanUp (0, 0);\r\n\r\n\tSetToolCursor (tool, TRUE);\r\n\r\n\tgMovingHands := FALSE\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nFUNCTION DoEraserTool (view: TImageView; magic: BOOLEAN): TCommand;\r\n\r\n\tVAR\r\n\t\tfi: FailInfo;\r\n\t\tanEraserTool: TEraserTool;\r\n\r\n\tPROCEDURE CleanUp (error: INTEGER; message: LONGINT);\r\n\t\tBEGIN\r\n\t\tIF magic THEN\r\n\t\t\tFailNewMessage (error, message, msgCannotMagic)\r\n\t\tELSE\r\n\t\t\tFailNewMessage (error, message, msgCannotErase)\r\n\t\tEND;\r\n\r\n\tBEGIN\r\n\r\n\tCatchFailures (fi, CleanUp);\r\n\r\n\tFailBadMode (view, FALSE, NormalDrawing);\r\n\r\n\tIF magic THEN GetMagicData (view, MagicTool, TRUE);\r\n\r\n\tNEW (anEraserTool);\r\n\tFailNil (anEraserTool);\r\n\r\n\tanEraserTool.IEraserTool (view, magic);\r\n\r\n\tSuccess (fi);\r\n\r\n\tDoEraserTool := anEraserTool\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TDrawingTool.IDrawingTool (view: TImageView;\r\n\t\t\t\t\t\t\t\t\t itsCommand: INTEGER;\r\n\t\t\t\t\t\t\t\t\t VAR tip: TTip;\r\n\t\t\t\t\t\t\t\t\t mode: TDrawingMode;\r\n\t\t\t\t\t\t\t\t\t spacing: INTEGER;\r\n\t\t\t\t\t\t\t\t\t fadeout: INTEGER;\r\n\t\t\t\t\t\t\t\t\t rate: INTEGER;\r\n\t\t\t\t\t\t\t\t\t failMessage: LONGINT;\r\n\t\t\t\t\t\t\t\t\t needAlpha: BOOLEAN);\r\n\r\n\tCONST\r\n\t\tkCallOverhead = 200;\r\n\r\n\tVAR\r\n\t\ts: LONGINT;\r\n\t\tp: LONGINT;\r\n\t\tmag: INTEGER;\r\n\t\tgoal: INTEGER;\r\n\t\tcacheSize: Point;\r\n\t\tmaxInvalid: INTEGER;\r\n\r\n\tBEGIN\r\n\r\n\tfTip\t := tip;\r\n\tfMode\t := mode;\r\n\tfSpacing := spacing;\r\n\tfFadeout := fadeout;\r\n\r\n\tIF rate = 0 THEN\r\n\t\tfDelay := 0\r\n\tELSE\r\n\t\tfDelay := 60 DIV rate;\r\n\r\n\tfPressureMode := 0;\r\n\r\n\tfStampMethod := -1;\r\n\r\n\tfTextureNoise := NIL;\r\n\r\n\ts := Max (1, fSpacing);\r\n\tp := Max (fTip.fSize.h, fTip.fSize.v);\r\n\r\n\tmag := view.fMagnification;\r\n\r\n\tIF mag &gt; 1 THEN\r\n\t\tBEGIN\r\n\t\ts := s * mag;\r\n\t\tp := p * mag\r\n\t\tEND\r\n\r\n\tELSE IF mag &lt; 1 THEN\r\n\t\tBEGIN\r\n\t\tmag := -mag;\r\n\t\ts := (s + mag - 1) DIV mag;\r\n\t\tp := (p + mag - 1) DIV mag\r\n\t\tEND;\r\n\r\n\tgoal := (SQR (p - s) + kCallOverhead) DIV SQR (s);\r\n\r\n\tmaxInvalid := 1;\r\n\r\n\tWHILE SQR (maxInvalid + 1) &lt;= goal DO\r\n\t\tmaxInvalid := maxInvalid + 1;\r\n\r\n\tcacheSize.h := fTip.fSize.h + maxInvalid - 1;\r\n\tcacheSize.v := fTip.fSize.v + maxInvalid - 1;\r\n\r\n\tview.CvtImage2View (cacheSize, kRoundUp);\r\n\r\n\tIMarkingTool (view, itsCommand, cacheSize, failMessage, needAlpha);\r\n\r\n\tfSpacingCounter := 1;\r\n\r\n\tfDrawings := 0\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TDrawingTool.Free; OVERRIDE;\r\n\r\n\tVAR\r\n\t\ttip: TTip;\r\n\r\n\tBEGIN\r\n\r\n\ttip := fTip;\r\n\r\n\tFreeTip (tip);\r\n\r\n\tIF fTextureNoise &lt;&gt; NIL THEN DisposHandle (fTextureNoise);\r\n\r\n\tINHERITED Free\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$IFC qTrace} {$D+} {$ENDC}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TDrawingTool.FindMask (offset: LONGINT; r: Rect);\r\n\r\n\tVAR\r\n\t\talphaPtr: Ptr;\r\n\r\n\tBEGIN\r\n\r\n\tBlockMove (fTip.fMask^,\r\n\t\t\t   fTip.fMask2^,\r\n\t\t\t   fTip.fSize.h * fTip.fSize.v);\r\n\r\n\tIF fAlphaChannel &lt;&gt; NIL THEN\r\n\t\tBEGIN\r\n\r\n\t\talphaPtr := fAlphaChannel.NeedPtr (r.top, r.bottom - 1, TRUE);\r\n\r\n\t\tDoAlphaMask (Ptr (ORD4 (fTip.fMask2^) + offset),\r\n\t\t\t\t\t Ptr (ORD4 (alphaPtr) + r.left),\r\n\t\t\t\t\t fTip.fSize.h,\r\n\t\t\t\t\t fAlphaChannel.fPhysicalSize,\r\n\t\t\t\t\t r.bottom - r.top,\r\n\t\t\t\t\t r.right - r.left);\r\n\r\n\t\tfAlphaChannel.DoneWithPtr\r\n\r\n\t\tEND\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TDrawingTool.BlurOrSharpen (dataPtr: Ptr;\r\n\t\t\t\t\t\t\t\t\t  offset: LONGINT;\r\n\t\t\t\t\t\t\t\t\t  r: Rect;\r\n\t\t\t\t\t\t\t\t\t  band: INTEGER;\r\n\t\t\t\t\t\t\t\t\t  sharpen: BOOLEAN);\r\n\r\n\tVAR\r\n\t\trr: Rect;\r\n\t\trrr: Rect;\r\n\t\tsrcPtr: Ptr;\r\n\t\tsrcWidth: INTEGER;\r\n\t\ttempWidth: INTEGER;\r\n\t\ttempHeight: INTEGER;\r\n\r\n\tBEGIN\r\n\r\n\tIF (r.top  = 0) OR (r.bottom = fDoc.fRows) OR\r\n\t   (r.left = 0) OR (r.right  = fDoc.fCols) THEN\r\n\t\tBEGIN\r\n\r\n\t\trr := r;\r\n\r\n\t\tInsetRect (rr, -1, -1);\r\n\r\n\t\ttempWidth  := rr.right - rr.left;\r\n\t\ttempHeight := rr.bottom - rr.top;\r\n\r\n\t\trrr := rr;\r\n\r\n\t\tIF rrr.top\t  &lt; 0\t\t   THEN rrr.top    := 0;\r\n\t\tIF rrr.left   &lt; 0\t\t   THEN rrr.left   := 0;\r\n\t\tIF rrr.bottom &gt; fDoc.fRows THEN rrr.bottom := fDoc.fRows;\r\n\t\tIF rrr.right  &gt; fDoc.fCols THEN rrr.right  := fDoc.fCols;\r\n\r\n\t\tDoGetTip (Ptr (ORD4 (dataPtr) +\r\n\t\t\t\t\t   ORD4 (rrr.top - r.top) * fPhysicalSize +\r\n\t\t\t\t\t   (rrr.left - r.left)),\r\n\t\t\t\t  Ptr (ORD4 (gBuffer) +\r\n\t\t\t\t\t   (rrr.top - rr.top) * tempWidth +\r\n\t\t\t\t\t   (rrr.left - rr.left)),\r\n\t\t\t\t  fPhysicalSize,\r\n\t\t\t\t  tempWidth,\r\n\t\t\t\t  rrr.bottom - rrr.top,\r\n\t\t\t\t  rrr.right - rrr.left);\r\n\r\n\t\tIF r.top = 0 THEN\r\n\t\t\tDoGetTip (Ptr (ORD4 (gBuffer) + tempWidth),\r\n\t\t\t\t\t  gBuffer,\r\n\t\t\t\t\t  tempWidth,\r\n\t\t\t\t\t  tempWidth,\r\n\t\t\t\t\t  \u06f1,\r\n\t\t\t\t\t  tempWidth);\r\n\r\n\t\tIF r.bottom = fDoc.fRows THEN\r\n\t\t\tDoGetTip (Ptr (ORD4 (gBuffer) + (tempHeight - 2) * tempWidth),\r\n\t\t\t\t\t  Ptr (ORD4 (gBuffer) + (tempHeight - 1) * tempWidth),\r\n\t\t\t\t\t  tempWidth,\r\n\t\t\t\t\t  tempWidth,\r\n\t\t\t\t\t  \u06f1,\r\n\t\t\t\t\t  tempWidth);\r\n\r\n\t\tIF r.left = 0 THEN\r\n\t\t\tDoGetTip (Ptr (ORD4 (gBuffer) + 1),\r\n\t\t\t\t\t  gBuffer,\r\n\t\t\t\t\t  tempWidth,\r\n\t\t\t\t\t  tempWidth,\r\n\t\t\t\t\t  tempHeight,\r\n\t\t\t\t\t  \u06f1);\r\n\r\n\t\tIF r.right = fDoc.fCols THEN\r\n\t\t\tDoGetTip (Ptr (ORD4 (gBuffer) + tempWidth - 2),\r\n\t\t\t\t\t  Ptr (ORD4 (gBuffer) + tempWidth - 1),\r\n\t\t\t\t\t  tempWidth,\r\n\t\t\t\t\t  tempWidth,\r\n\t\t\t\t\t  tempHeight,\r\n\t\t\t\t\t  \u06f1);\r\n\r\n\t\tsrcPtr\t := Ptr (ORD4 (gBuffer) + tempWidth + 1);\r\n\t\tsrcWidth := tempWidth\r\n\r\n\t\tEND\r\n\r\n\tELSE\r\n\t\tBEGIN\r\n\t\tsrcPtr\t := dataPtr;\r\n\t\tsrcWidth := fPhysicalSize\r\n\t\tEND;\r\n\r\n\tIF sharpen THEN\r\n\t\tDoGetSharpened (srcPtr,\r\n\t\t\t\t\t\tPtr (ORD4 (fTip.fData [band]^) + offset),\r\n\t\t\t\t\t\tsrcWidth,\r\n\t\t\t\t\t\tfTip.fSize.h,\r\n\t\t\t\t\t\tr.bottom - r.top,\r\n\t\t\t\t\t\tr.right - r.left)\r\n\r\n\tELSE\r\n\t\tDoGetBlurred (srcPtr,\r\n\t\t\t\t\t  Ptr (ORD4 (fTip.fData [band]^) + offset),\r\n\t\t\t\t\t  srcWidth,\r\n\t\t\t\t\t  fTip.fSize.h,\r\n\t\t\t\t\t  r.bottom - r.top,\r\n\t\t\t\t\t  r.right - r.left)\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TDrawingTool.SmudgeBand (dataPtr: Ptr;\r\n\t\t\t\t\t\t\t\t   offset: LONGINT;\r\n\t\t\t\t\t\t\t\t   r: Rect;\r\n\t\t\t\t\t\t\t\t   band: INTEGER);\r\n\r\n\tBEGIN\r\n\r\n\tDoGetTip (dataPtr,\r\n\t\t\t  Ptr (ORD4 (fTip.fData [0]^) + offset),\r\n\t\t\t  fPhysicalSize,\r\n\t\t\t  fTip.fSize.h,\r\n\t\t\t  r.bottom - r.top,\r\n\t\t\t  r.right - r.left);\r\n\r\n\tIF fDrawings &lt;&gt; 0 THEN\r\n\t\tDoMixBytes (fTip.fData [band]^,\r\n\t\t\t\t\tfTip.fData [0]^,\r\n\t\t\t\t\tfMixMap,\r\n\t\t\t\t\tfTip.fSize.h * fTip.fSize.v)\r\n\r\n\tELSE IF NOT fDip THEN\r\n\t\tBlockMove (fTip.fData [0]^,\r\n\t\t\t\t   fTip.fData [band]^,\r\n\t\t\t\t   fTip.fSize.h * fTip.fSize.v)\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TDrawingTool.MarkBand (dataPtr: Ptr;\r\n\t\t\t\t\t\t\t\t offset: LONGINT;\r\n\t\t\t\t\t\t\t\t r: Rect;\r\n\t\t\t\t\t\t\t\t band: INTEGER);\r\n\r\n\tVAR\r\n\t\tnoiseOffset: LONGINT;\r\n\r\n\tBEGIN\r\n\r\n\tIF (fCmdNumber = cBlurring) OR (fCmdNumber = cSharpening) THEN\r\n\t\tBlurOrSharpen (dataPtr, offset, r, band, fCmdNumber = cSharpening)\r\n\r\n\tELSE IF fCmdNumber = cSmudging THEN\r\n\t\tSmudgeBand (dataPtr, offset, r, band);\r\n\r\n\tIF fMode = DarkenOnly THEN\r\n\t\tDoDrawTipDarken (dataPtr,\r\n\t\t\t\t\t\t Ptr (ORD4 (fTip.fMask2^) + offset),\r\n\t\t\t\t\t\t Ptr (ORD4 (fTip.fData [band]^) + offset),\r\n\t\t\t\t\t\t fPhysicalSize,\r\n\t\t\t\t\t\t fTip.fSize.h,\r\n\t\t\t\t\t\t r.bottom - r.top,\r\n\t\t\t\t\t\t r.right - r.left)\r\n\r\n\tELSE IF fMode = LightenOnly THEN\r\n\t\tDoDrawTipLighten (dataPtr,\r\n\t\t\t\t\t\t  Ptr (ORD4 (fTip.fMask2^) + offset),\r\n\t\t\t\t\t\t  Ptr (ORD4 (fTip.fData [band]^) + offset),\r\n\t\t\t\t\t\t  fPhysicalSize,\r\n\t\t\t\t\t\t  fTip.fSize.h,\r\n\t\t\t\t\t\t  r.bottom - r.top,\r\n\t\t\t\t\t\t  r.right - r.left)\r\n\r\n\tELSE\r\n\t\tDoDrawTip (dataPtr,\r\n\t\t\t\t   Ptr (ORD4 (fTip.fMask2^) + offset),\r\n\t\t\t\t   Ptr (ORD4 (fTip.fData [band]^) + offset),\r\n\t\t\t\t   fPhysicalSize,\r\n\t\t\t\t   fTip.fSize.h,\r\n\t\t\t\t   r.bottom - r.top,\r\n\t\t\t\t   r.right - r.left);\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TDrawingTool.MarkRGB (rDataPtr: Ptr;\r\n\t\t\t\t\t\t\t\tgDataPtr: Ptr;\r\n\t\t\t\t\t\t\t\tbDataPtr: Ptr;\r\n\t\t\t\t\t\t\t\toffset: LONGINT;\r\n\t\t\t\t\t\t\t\tr: Rect);\r\n\r\n\tVAR\r\n\t\tband: INTEGER;\r\n\t\tsharpen: BOOLEAN;\r\n\t\tnoiseOffset: LONGINT;\r\n\r\n\tBEGIN\r\n\r\n\tIF fMode &lt;&gt; ColorOnly THEN\r\n\t\tBEGIN\r\n\t\tMarkBand (rDataPtr, offset, r, 1);\r\n\t\tMarkBand (gDataPtr, offset, r, 2);\r\n\t\tMarkBand (bDataPtr, offset, r, 3)\r\n\t\tEND\r\n\r\n\tELSE\r\n\t\tBEGIN\r\n\r\n\t\tIF (fCmdNumber = cBlurring) OR (fCmdNumber = cSharpening) THEN\r\n\t\t\tBEGIN\r\n\t\t\tsharpen := (fCmdNumber = cSharpening);\r\n\t\t\tBlurOrSharpen (rDataPtr, offset, r, 1, sharpen);\r\n\t\t\tBlurOrSharpen (gDataPtr, offset, r, 2, sharpen);\r\n\t\t\tBlurOrSharpen (bDataPtr, offset, r, 3, sharpen)\r\n\t\t\tEND\r\n\r\n\t\tELSE IF fCmdNumber = cSmudging THEN\r\n\t\t\tBEGIN\r\n\t\t\tSmudgeBand (rDataPtr, offset, r, 1);\r\n\t\t\tSmudgeBand (gDataPtr, offset, r, 2);\r\n\t\t\tSmudgeBand (bDataPtr, offset, r, 3)\r\n\t\t\tEND;\r\n\r\n\t\tDoDrawTipColor (gGrayLUT,\r\n\t\t\t\t\t\trDataPtr,\r\n\t\t\t\t\t\tgDataPtr,\r\n\t\t\t\t\t\tbDataPtr,\r\n\t\t\t\t\t\tPtr (ORD4 (fTip.fMask2^) + offset),\r\n\t\t\t\t\t\tPtr (ORD4 (fTip.fData [1]^) + offset),\r\n\t\t\t\t\t\tPtr (ORD4 (fTip.fData [2]^) + offset),\r\n\t\t\t\t\t\tPtr (ORD4 (fTip.fData [3]^) + offset),\r\n\t\t\t\t\t\tfPhysicalSize,\r\n\t\t\t\t\t\tfTip.fSize.h,\r\n\t\t\t\t\t\tr.bottom - r.top,\r\n\t\t\t\t\t\tr.right - r.left)\r\n\r\n\t\tEND\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TDrawingTool.LoadOverlap (r: Rect;\r\n\t\t\t\t\t\t\t\t\tsrcArray1: TVMArray;\r\n\t\t\t\t\t\t\t\t\tsrcArray2: TVMArray;\r\n\t\t\t\t\t\t\t\t\tsrcArray3: TVMArray);\r\n\r\n\tVAR\r\n\t\trr: Rect;\r\n\t\trows: INTEGER;\r\n\t\tcols: INTEGER;\r\n\t\toffset: LONGINT;\r\n\r\n\tPROCEDURE DoLoadOverlap (srcArray: TVMArray; band: INTEGER);\r\n\r\n\t\tVAR\r\n\t\t\tsrcPtr: Ptr;\r\n\r\n\t\tBEGIN\r\n\r\n\t\tsrcPtr := srcArray.NeedPtr (rr.top, rr.bottom - 1, FALSE);\r\n\r\n\t\tDoGetTip (Ptr (ORD4 (srcPtr) + rr.left),\r\n\t\t\t\t  Ptr (ORD4 (fTip.fData [band]^) + offset),\r\n\t\t\t\t  srcArray.fPhysicalSize,\r\n\t\t\t\t  fTip.fSize.h,\r\n\t\t\t\t  rr.bottom - rr.top,\r\n\t\t\t\t  rr.right - rr.left);\r\n\r\n\t\tsrcArray.DoneWithPtr\r\n\r\n\t\tEND;\r\n\r\n\tBEGIN\r\n\r\n\trr := r;\r\n\r\n\toffset := 0;\r\n\r\n\trows := srcArray1.fBlockCount;\r\n\tcols := srcArray1.fLogicalSize;\r\n\r\n\tIF (rr.top\t&lt; 0) OR (rr.bottom &gt; rows) OR\r\n\t   (rr.left &lt; 0) OR (rr.right  &gt; cols) THEN\r\n\t\tBEGIN\r\n\r\n\t\tIF rr.left &lt; 0 THEN\r\n\t\t\tBEGIN\r\n\t\t\toffset\t:= -rr.left;\r\n\t\t\trr.left := 0\r\n\t\t\tEND;\r\n\r\n\t\tIF rr.top &lt; 0 THEN\r\n\t\t\tBEGIN\r\n\t\t\toffset := offset - rr.top * fTip.fSize.h;\r\n\t\t\trr.top := 0\r\n\t\t\tEND;\r\n\r\n\t\tIF rr.right &gt; cols THEN\r\n\t\t\trr.right := cols;\r\n\r\n\t\tIF rr.bottom &gt; rows THEN\r\n\t\t\trr.bottom := rows\r\n\r\n\t\tEND;\r\n\r\n\tDoLoadOverlap (srcArray1, 1);\r\n\r\n\tIF srcArray2 &lt;&gt; NIL THEN\r\n\t\tBEGIN\r\n\t\tDoLoadOverlap (srcArray2, 2);\r\n\t\tDoLoadOverlap (srcArray3, 3)\r\n\t\tEND\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TDrawingTool.LoadCloneTip (r: Rect);\r\n\r\n\tVAR\r\n\t\trr: Rect;\r\n\t\tj: INTEGER;\r\n\t\twidth: INTEGER;\r\n\t\theight: INTEGER;\r\n\t\toffset: LONGINT;\r\n\t\tbuffer: ARRAY [0..2] OF Ptr;\r\n\r\n\tPROCEDURE DoMoveClone (srcArray: TVMArray;\r\n\t\t\t\t\t\t   srcRect: Rect;\r\n\t\t\t\t\t\t   dstPtr: Ptr;\r\n\t\t\t\t\t\t   dstWidth: INTEGER);\r\n\r\n\t\tVAR\r\n\t\t\tsrcPtr: Ptr;\r\n\r\n\t\tBEGIN\r\n\r\n\t\tsrcPtr := srcArray.NeedPtr (srcRect.top,\r\n\t\t\t\t\t\t\t\t\tsrcRect.bottom - 1, FALSE);\r\n\r\n\t\tDoGetTip (Ptr (ORD4 (srcPtr) + srcRect.left),\r\n\t\t\t\t  dstPtr,\r\n\t\t\t\t  srcArray.fPhysicalSize,\r\n\t\t\t\t  dstWidth,\r\n\t\t\t\t  srcRect.bottom - srcRect.top,\r\n\t\t\t\t  srcRect.right - srcRect.left);\r\n\r\n\t\tsrcArray.DoneWithPtr\r\n\r\n\t\tEND;\r\n\r\n\tPROCEDURE DoLoadClone (srcArray: TVMArray; band: INTEGER);\r\n\r\n\t\tBEGIN\r\n\r\n\t\tDoMoveClone (srcArray,\r\n\t\t\t\t\t rr,\r\n\t\t\t\t\t Ptr (ORD4 (fTip.fData [band]^) + offset),\r\n\t\t\t\t\t fTip.fSize.h)\r\n\r\n\t\tEND;\r\n\r\n\tBEGIN\r\n\r\n\trr := r;\r\n\r\n\tOffsetRect (rr, fStampOffset.h, fStampOffset.v);\r\n\r\n\toffset := 0;\r\n\r\n\tIF (rr.top\t&lt; 0) OR (rr.bottom &gt; gCloneDoc.fRows) OR\r\n\t   (rr.left &lt; 0) OR (rr.right  &gt; gCloneDoc.fCols) THEN\r\n\t\tBEGIN\r\n\r\n\t\tIF fChannel = kRGBChannels THEN\r\n\t\t\tLoadOverlap (r, fDoc.fData [0], fDoc.fData [1], fDoc.fData [2])\r\n\t\tELSE\r\n\t\t\tLoadOverlap (r, fDoc.fData [fChannel], NIL, NIL);\r\n\r\n\t\tIF rr.left &lt; 0 THEN\r\n\t\t\tBEGIN\r\n\t\t\toffset\t:= -rr.left;\r\n\t\t\trr.left := 0\r\n\t\t\tEND;\r\n\r\n\t\tIF rr.top &lt; 0 THEN\r\n\t\t\tBEGIN\r\n\t\t\toffset := offset - rr.top * fTip.fSize.h;\r\n\t\t\trr.top := 0\r\n\t\t\tEND;\r\n\r\n\t\tIF rr.right &gt; gCloneDoc.fCols THEN\r\n\t\t\trr.right := gCloneDoc.fCols;\r\n\r\n\t\tIF rr.bottom &gt; gCloneDoc.fRows THEN\r\n\t\t\trr.bottom := gCloneDoc.fRows;\r\n\r\n\t\tIF EmptyRect (rr) THEN EXIT (LoadCloneTip)\r\n\r\n\t\tEND;\r\n\r\n\tIF fChannel = kRGBChannels THEN\r\n\t\tBEGIN\r\n\r\n\t\tIF gCloneChannel = kRGBChannels THEN\r\n\r\n\t\t\tIF fDoc = gCloneDoc THEN\r\n\t\t\t\tBEGIN\r\n\t\t\t\tSaveLines (rr.top, rr.bottom - 1);\r\n\t\t\t\tDoLoadClone (fBuffer [0], 1);\r\n\t\t\t\tDoLoadClone (fBuffer [1], 2);\r\n\t\t\t\tDoLoadClone (fBuffer [2], 3)\r\n\t\t\t\tEND\r\n\r\n\t\t\tELSE\r\n\t\t\t\tBEGIN\r\n\t\t\t\tDoLoadClone (gCloneDoc.fData [0], 1);\r\n\t\t\t\tDoLoadClone (gCloneDoc.fData [1], 2);\r\n\t\t\t\tDoLoadClone (gCloneDoc.fData [2], 3)\r\n\t\t\t\tEND\r\n\r\n\t\tELSE IF (gCloneChannel &lt;= 2) AND (fDoc = gCloneDoc) THEN\r\n\t\t\tBEGIN\r\n\t\t\tSaveLines (rr.top, rr.bottom - 1);\r\n\t\t\tDoLoadClone (fBuffer [gCloneChannel], 1);\r\n\t\t\tDoLoadClone (fBuffer [gCloneChannel], 2);\r\n\t\t\tDoLoadClone (fBuffer [gCloneChannel], 3)\r\n\t\t\tEND\r\n\r\n\t\tELSE\r\n\t\t\tBEGIN\r\n\t\t\tDoLoadClone (gCloneDoc.fData [gCloneChannel], 1);\r\n\t\t\tDoLoadClone (gCloneDoc.fData [gCloneChannel], 2);\r\n\t\t\tDoLoadClone (gCloneDoc.fData [gCloneChannel], 3)\r\n\t\t\tEND\r\n\r\n\t\tEND\r\n\r\n\tELSE IF gCloneChannel = kRGBChannels THEN\r\n\t\tBEGIN\r\n\r\n\t\tIF (fDoc = gCloneDoc) AND (fChannel &lt;= 2) THEN\r\n\t\t\tSaveLines (rr.top, rr.bottom - 1);\r\n\r\n\t\tbuffer [0] := gBuffer;\r\n\t\tbuffer [1] := Ptr (ORD4 (buffer [0]) + kMaxTipArea);\r\n\t\tbuffer [2] := Ptr (ORD4 (buffer [1]) + kMaxTipArea);\r\n\r\n\t\twidth  := rr.right - rr.left;\r\n\t\theight := rr.bottom - rr.top;\r\n\r\n\t\tFOR j := 0 TO 2 DO\r\n\t\t\tIF (fDoc = gCloneDoc) AND (fChannel = j) THEN\r\n\t\t\t\tDoMoveClone (fBuffer [0], rr, buffer [j], width)\r\n\t\t\tELSE\r\n\t\t\t\tDoMoveClone (gCloneDoc.fData [j], rr, buffer [j], width);\r\n\r\n\t\tDoMakeMonochrome (buffer [0], gGrayLUT.R,\r\n\t\t\t\t\t\t  buffer [1], gGrayLUT.G,\r\n\t\t\t\t\t\t  buffer [2], gGrayLUT.B,\r\n\t\t\t\t\t\t  buffer [0], width * height);\r\n\r\n\t\tDoGetTip (buffer [0],\r\n\t\t\t\t  Ptr (ORD4 (fTip.fData [1]^) + offset),\r\n\t\t\t\t  width,\r\n\t\t\t\t  fTip.fSize.h,\r\n\t\t\t\t  height,\r\n\t\t\t\t  width)\r\n\r\n\t\tEND\r\n\r\n\tELSE IF (fDoc = gCloneDoc) AND (fChannel = gCloneChannel) THEN\r\n\t\tBEGIN\r\n\t\tSaveLines (rr.top, rr.bottom - 1);\r\n\t\tDoLoadClone (fBuffer [0], 1)\r\n\t\tEND\r\n\r\n\tELSE\r\n\t\tDoLoadClone (gCloneDoc.fData [gCloneChannel], 1)\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TDrawingTool.LoadRevertTip (r: Rect);\r\n\r\n\tBEGIN\r\n\r\n\tIF fChannel = kRGBChannels THEN\r\n\t\tLoadOverlap (r,\r\n\t\t\t\t\t fDoc.fMagicData [0],\r\n\t\t\t\t\t fDoc.fMagicData [1],\r\n\t\t\t\t\t fDoc.fMagicData [2])\r\n\tELSE\r\n\t\tLoadOverlap (r,\r\n\t\t\t\t\t fDoc.fMagicData [fChannel],\r\n\t\t\t\t\t NIL,\r\n\t\t\t\t\t NIL)\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TDrawingTool.LoadTextureTip;\r\n\r\n\tVAR\r\n\t\tnoisePtr: Ptr;\r\n\t\tpixels: INTEGER;\r\n\r\n\tBEGIN\r\n\r\n\tnoisePtr := Ptr (ORD4 (fTextureNoise^) + BAND (fDrawings, $F));\r\n\r\n\tIF fChannel = kRGBChannels THEN\r\n\t\tBEGIN\r\n\t\tScrambleTexture (@gTexture [1], noisePtr);\r\n\t\tScrambleTexture (@gTexture [2], noisePtr);\r\n\t\tScrambleTexture (@gTexture [3], noisePtr)\r\n\t\tEND\r\n\tELSE\r\n\t\tScrambleTexture (@gTexture [0], noisePtr);\r\n\r\n\tpixels := fTip.fSize.h * fTip.fSize.v;\r\n\r\n\tBlockMove (fTextureNoise^, fTip.fData [1]^, pixels);\r\n\r\n\tIF fChannel = kRGBChannels THEN\r\n\t\tBEGIN\r\n\r\n\t\tBlockMove (fTip.fData [1]^, fTip.fData [2]^, pixels);\r\n\t\tBlockMove (fTip.fData [1]^, fTip.fData [3]^, pixels);\r\n\r\n\t\tDoMapBytes (fTip.fData [1]^, pixels, gTexture [1]);\r\n\t\tDoMapBytes (fTip.fData [2]^, pixels, gTexture [2]);\r\n\t\tDoMapBytes (fTip.fData [3]^, pixels, gTexture [3])\r\n\r\n\t\tEND\r\n\r\n\tELSE\r\n\t\tDoMapBytes (fTip.fData [1]^, pixels, gTexture [0])\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TDrawingTool.LoadPatternTip (r: Rect);\r\n\r\n\tVAR\r\n\t\tpt: Point;\r\n\t\twidth: INTEGER;\r\n\t\theight: INTEGER;\r\n\r\n\tPROCEDURE DoLoadPattern (srcArray: TVMArray; band: INTEGER);\r\n\r\n\t\tVAR\r\n\t\t\tsrcPtr: Ptr;\r\n\r\n\t\tBEGIN\r\n\r\n\t\tsrcPtr := srcArray.NeedPtr (pt.v,\r\n\t\t\t\t\t\t\t\t\tpt.v + r.bottom - r.top - 1,\r\n\t\t\t\t\t\t\t\t\tFALSE);\r\n\r\n\t\tDoGetTip (Ptr (ORD4 (srcPtr) + pt.h),\r\n\t\t\t\t  fTip.fData [band]^,\r\n\t\t\t\t  srcArray.fPhysicalSize,\r\n\t\t\t\t  fTip.fSize.h,\r\n\t\t\t\t  r.bottom - r.top,\r\n\t\t\t\t  r.right - r.left);\r\n\r\n\t\tsrcArray.DoneWithPtr\r\n\r\n\t\tEND;\r\n\r\n\tBEGIN\r\n\r\n\twidth  := gPatternRect.right - gPatternRect.left;\r\n\theight := gPatternRect.bottom - gPatternRect.top;\r\n\r\n\tpt := r.topLeft;\r\n\r\n\tpt.v := pt.v + gPatternRect.top  - fStampOffset.v;\r\n\tpt.h := pt.h + gPatternRect.left - fStampOffset.h;\r\n\r\n\tIF pt.v &lt; 0 THEN\r\n\t\tpt.v := height - 1 - (-pt.v - 1) MOD height\r\n\tELSE\r\n\t\tpt.v := pt.v MOD height;\r\n\r\n\tIF pt.h &lt; 0 THEN\r\n\t\tpt.h := width - 1 - (-pt.h - 1) MOD width\r\n\tELSE\r\n\t\tpt.h := pt.h MOD width;\r\n\r\n\tIF fChannel = kRGBChannels THEN\r\n\r\n\t\tIF gPattern [1] &lt;&gt; NIL THEN\r\n\t\t\tBEGIN\r\n\t\t\tDoLoadPattern (gPattern [1], 1);\r\n\t\t\tDoLoadPattern (gPattern [2], 2);\r\n\t\t\tDoLoadPattern (gPattern [3], 3)\r\n\t\t\tEND\r\n\r\n\t\tELSE\r\n\t\t\tBEGIN\r\n\t\t\tDoLoadPattern (gPattern [0], 1);\r\n\t\t\tDoLoadPattern (gPattern [0], 2);\r\n\t\t\tDoLoadPattern (gPattern [0], 3)\r\n\t\t\tEND\r\n\r\n\tELSE\r\n\t\tDoLoadPattern (gPattern [0], 1)\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TDrawingTool.LoadImpressTip (pt: Point);\r\n\r\n\tPROCEDURE DoLoadImpress (srcArray: TVMArray; band: INTEGER);\r\n\r\n\t\tVAR\r\n\t\t\tp: Ptr;\r\n\r\n\t\tBEGIN\r\n\r\n\t\tp := Ptr (ORD4 (srcArray.NeedPtr (pt.v, pt.v, FALSE)) + pt.h);\r\n\r\n\t\tDoSetBytes (fTip.fData [band]^, fTip.fSize.h * fTip.fSize.v, p^);\r\n\r\n\t\tsrcArray.DoneWithPtr\r\n\r\n\t\tEND;\r\n\r\n\tBEGIN\r\n\r\n\t{$IFC qBarneyscan}\r\n\tFailure (errNotYetImp, 0);\r\n\t{$ENDC}\r\n\r\n\tfImpressCounter := fImpressCounter - 1;\r\n\r\n\tIF fImpressCounter &gt;= 0 THEN EXIT (LoadImpressTip);\r\n\r\n\tIF fSpacing = 1 THEN\r\n\t\tfImpressCounter := Max (fTip.fSize.h, fTip.fSize.v)\r\n\tELSE\r\n\t\tfImpressCounter := 0;\r\n\r\n\tfImpressTimer := TickCount;\r\n\r\n\tIF fChannel = kRGBChannels THEN\r\n\t\tBEGIN\r\n\t\tDoLoadImpress (fDoc.fMagicData [0], 1);\r\n\t\tDoLoadImpress (fDoc.fMagicData [1], 2);\r\n\t\tDoLoadImpress (fDoc.fMagicData [2], 3)\r\n\t\tEND\r\n\tELSE\r\n\t\tDoLoadImpress (fDoc.fMagicData [fChannel], 1)\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nFUNCTION TDrawingTool.TrackMouse (aTrackPhase: TrackPhase;\r\n\t\t\t\t\t\t\t\t  VAR anchorPoint: Point;\r\n\t\t\t\t\t\t\t\t  VAR previousPoint: Point;\r\n\t\t\t\t\t\t\t\t  VAR nextPoint: Point;\r\n\t\t\t\t\t\t\t\t  mouseDidMove: BOOLEAN): TCommand; OVERRIDE;\r\n\r\n\tVAR\r\n\t\tpt1: Point;\r\n\t\tpt2: Point;\r\n\t\tfi: FailInfo;\r\n\t\tmag: INTEGER;\r\n\t\tauxPt: Point;\r\n\t\tbounds: Rect;\r\n\t\tdataPtr: Ptr;\r\n\t\trows: INTEGER;\r\n\t\tcols: INTEGER;\r\n\t\trDataPtr: Ptr;\r\n\t\tgDataPtr: Ptr;\r\n\t\tbDataPtr: Ptr;\r\n\t\tauxMag: INTEGER;\r\n\r\n\tPROCEDURE MarkPoint (pt: Point);\r\n\r\n\t\tVAR\r\n\t\t\tr: Rect;\r\n\t\t\tp: INTEGER;\r\n\t\t\ttipPtr: Ptr;\r\n\t\t\tupper: INTEGER;\r\n\t\t\tlower: INTEGER;\r\n\t\t\tdelta: LONGINT;\r\n\t\t\tpixels: INTEGER;\r\n\t\t\toffset: LONGINT;\r\n\t\t\tchannel: INTEGER;\r\n\t\t\tchannels: INTEGER;\r\n\r\n\t\tBEGIN\r\n\r\n\t\tfSpacingCounter := fSpacingCounter - 1;\r\n\r\n\t\tIF fSpacingCounter &lt;= 0 THEN\r\n\t\t\tBEGIN\r\n\r\n\t\t\tfSpacingCounter := fSpacing;\r\n\r\n\t\t\tpixels := fTip.fSize.h * fTip.fSize.v;\r\n\r\n\t\t\tIF (fDrawings = 0) AND ((fPressureMode &lt;&gt; 0) OR\r\n\t\t\t\t\t\t\t\t\t(fFadeout &gt; 0)) THEN\r\n\t\t\t\tBlockMove (fTip.fMask^, fTip.fData [0]^, pixels);\r\n\r\n\t\t\ttipPtr := fTip.fData [0]^;\r\n\r\n\t\t\tIF fPressureMode &lt;&gt; 0 THEN\r\n\t\t\t\tBEGIN\r\n\r\n\t\t\t\tp := ReadPressure;\r\n\r\n\t\t\t\tIF p = 0 THEN\r\n\t\t\t\t\tDoSetBytes (fTip.fMask^, pixels, 0)\r\n\r\n\t\t\t\tELSE IF fPressureMode = 1 THEN\r\n\t\t\t\t\tDoThresholdMask (tipPtr, fTip.fMask^, pixels, p)\r\n\r\n\t\t\t\tELSE IF fPressureMode = 2 THEN\r\n\t\t\t\t\tDoNarrowMask (tipPtr, fTip.fMask^, pixels, p)\r\n\r\n\t\t\t\tELSE\r\n\t\t\t\t\tDoFadeMask (tipPtr, fTip.fMask^, pixels, 255 - p, 255);\r\n\r\n\t\t\t\ttipPtr := fTip.fMask^\r\n\r\n\t\t\t\tEND;\r\n\r\n\t\t\tIF fFadeout &gt; 0 THEN\r\n\t\t\t\tBEGIN\r\n\r\n\t\t\t\tIF fDrawings &lt; fFadeout THEN\r\n\t\t\t\t\tDoFadeMask (tipPtr, fTip.fMask^, pixels,\r\n\t\t\t\t\t\t\t\tfDrawings, fFadeout)\r\n\r\n\t\t\t\tEND\r\n\r\n\t\t\tELSE IF fFadeout &lt; 0 THEN\r\n\t\t\t\tBEGIN\r\n\r\n\t\t\t\tIF fView.fChannel = kRGBChannels THEN\r\n\t\t\t\t\tchannels := 3\r\n\t\t\t\tELSE\r\n\t\t\t\t\tchannels := 1;\r\n\r\n\t\t\t\tIF fDrawings = 0 THEN\r\n\t\t\t\t\tFOR channel := 1 TO channels DO\r\n\t\t\t\t\t\tBEGIN\r\n\t\t\t\t\t\tfFore [channel] := fView.ForegroundByte (channel - 1);\r\n\t\t\t\t\t\tfBack [channel] := fView.BackgroundByte (channel - 1)\r\n\t\t\t\t\t\tEND\r\n\r\n\t\t\t\tELSE IF fDrawings &lt;= -fFadeout THEN\r\n\t\t\t\t\tFOR channel := 1 TO channels DO\r\n\t\t\t\t\t\tDoSetBytes (fTip.fData [channel]^, pixels,\r\n\t\t\t\t\t\t\t\t\t(fFore [channel] *\r\n\t\t\t\t\t\t\t\t\t ORD4 (fDrawings + fFadeout) -\r\n\t\t\t\t\t\t\t\t\t fBack [channel] *\r\n\t\t\t\t\t\t\t\t\t ORD4 (fDrawings)) DIV fFadeout)\r\n\r\n\t\t\t\tEND;\r\n\r\n\t\t\tIF (fFadeout &lt;= 0) OR (fDrawings &lt; fFadeout) THEN\r\n\t\t\t\tBEGIN\r\n\r\n\t\t\t\tr.top  := pt.v - fTip.fSpot.v;\r\n\t\t\t\tr.left := pt.h - fTip.fSpot.h;\r\n\r\n\t\t\t\tr.bottom := r.top  + fTip.fSize.v;\r\n\t\t\t\tr.right  := r.left + fTip.fSize.h;\r\n\r\n\t\t\t\tIF (r.bottom &gt; 0) AND (r.top  &lt; rows) AND\r\n\t\t\t\t   (r.right  &gt; 0) AND (r.left &lt; cols) THEN\r\n\t\t\t\t\tBEGIN\r\n\r\n\t\t\t\t\t\tCASE fStampMethod OF\r\n\r\n\t\t\t\t\t\tkClone1Method,\r\n\t\t\t\t\t\tkClone2Method:\r\n\t\t\t\t\t\t\tLoadCloneTip (r);\r\n\r\n\t\t\t\t\t\tkRevertMethod:\r\n\t\t\t\t\t\t\tLoadRevertTip (r);\r\n\r\n\t\t\t\t\t\tkTextureMethod:\r\n\t\t\t\t\t\t\tLoadTextureTip;\r\n\r\n\t\t\t\t\t\tkPattern1Method,\r\n\t\t\t\t\t\tkPattern2Method:\r\n\t\t\t\t\t\t\tLoadPatternTip (r);\r\n\r\n\t\t\t\t\t\tkImpressMethod:\r\n\t\t\t\t\t\t\tIF (pt.v &gt;= 0) AND (pt.v &lt; rows) AND\r\n\t\t\t\t\t\t\t   (pt.h &gt;= 0) AND (pt.h &lt; cols) THEN\r\n\t\t\t\t\t\t\t\tLoadImpressTip (pt)\r\n\r\n\t\t\t\t\t\tEND;\r\n\r\n\t\t\t\t\tIF r.bottom &gt; rows THEN r.bottom := rows;\r\n\t\t\t\t\tIF r.right\t&gt; cols THEN r.right  := cols;\r\n\r\n\t\t\t\t\toffset := 0;\r\n\r\n\t\t\t\t\tIF r.top &lt; 0 THEN\r\n\t\t\t\t\t\tBEGIN\r\n\t\t\t\t\t\toffset := fTip.fSize.h * (-r.top);\r\n\t\t\t\t\t\tr.top  := 0\r\n\t\t\t\t\t\tEND;\r\n\r\n\t\t\t\t\tIF r.left &lt; 0 THEN\r\n\t\t\t\t\t\tBEGIN\r\n\t\t\t\t\t\toffset := offset - r.left;\r\n\t\t\t\t\t\tr.left := 0\r\n\t\t\t\t\t\tEND;\r\n\r\n\t\t\t\t\tupper := r.top;\r\n\t\t\t\t\tlower := r.bottom;\r\n\r\n\t\t\t\t\tdelta := r.left;\r\n\r\n\t\t\t\t\tIF (fCmdNumber = cBlurring) OR\r\n\t\t\t\t\t   (fCmdNumber = cSharpening) THEN\r\n\t\t\t\t\t\tBEGIN\r\n\r\n\t\t\t\t\t\tIF upper &gt; 0 THEN\r\n\t\t\t\t\t\t\tBEGIN\r\n\t\t\t\t\t\t\tupper := upper - 1;\r\n\t\t\t\t\t\t\tdelta := delta + fPhysicalSize\r\n\t\t\t\t\t\t\tEND;\r\n\r\n\t\t\t\t\t\tIF lower &lt; rows THEN\r\n\t\t\t\t\t\t\tlower := lower + 1\r\n\r\n\t\t\t\t\t\tEND;\r\n\r\n\t\t\t\t\tAddToMarked (r);\r\n\r\n\t\t\t\t\tFindMask (offset, r);\r\n\r\n\t\t\t\t\tIF fChannel = kRGBChannels THEN\r\n\t\t\t\t\t\tBEGIN\r\n\r\n\t\t\t\t\t\trDataPtr := Ptr (ORD4 (fDoc.fData [0] . NeedPtr\r\n\t\t\t\t\t\t\t\t\t\t (upper, lower - 1, TRUE)) + delta);\r\n\r\n\t\t\t\t\t\tgDataPtr := Ptr (ORD4 (fDoc.fData [1] . NeedPtr\r\n\t\t\t\t\t\t\t\t\t\t (upper, lower - 1, TRUE)) + delta);\r\n\r\n\t\t\t\t\t\tbDataPtr := Ptr (ORD4 (fDoc.fData [2] . NeedPtr\r\n\t\t\t\t\t\t\t\t\t\t (upper, lower - 1, TRUE)) + delta);\r\n\r\n\t\t\t\t\t\tMarkRGB (rDataPtr, gDataPtr, bDataPtr, offset, r);\r\n\r\n\t\t\t\t\t\tfDoc.fData [0] . DoneWithPtr;\r\n\t\t\t\t\t\tfDoc.fData [1] . DoneWithPtr;\r\n\t\t\t\t\t\tfDoc.fData [2] . DoneWithPtr;\r\n\r\n\t\t\t\t\t\trDataPtr := NIL;\r\n\t\t\t\t\t\tgDataPtr := NIL;\r\n\t\t\t\t\t\tbDataPtr := NIL\r\n\r\n\t\t\t\t\t\tEND\r\n\r\n\t\t\t\t\tELSE\r\n\t\t\t\t\t\tBEGIN\r\n\r\n\t\t\t\t\t\tdataPtr := Ptr (ORD4 (fDoc.fData [fChannel] . NeedPtr\r\n\t\t\t\t\t\t\t\t\t\t(upper, lower - 1, TRUE)) + delta);\r\n\r\n\t\t\t\t\t\tMarkBand (dataPtr, offset, r, 1);\r\n\r\n\t\t\t\t\t\tfDoc.fData [fChannel] . DoneWithPtr;\r\n\r\n\t\t\t\t\t\tdataPtr := NIL\r\n\r\n\t\t\t\t\t\tEND;\r\n\r\n\t\t\t\t\tAddToCache (r)\r\n\r\n\t\t\t\t\tEND\r\n\r\n\t\t\t\tEND;\r\n\r\n\t\t\tfDrawings := fDrawings + 1\r\n\r\n\t\t\tEND\r\n\r\n\t\tEND;\r\n\r\n\tPROCEDURE FindAuxView (view: TImageView);\r\n\r\n\t\tBEGIN\r\n\t\tIF view.fChannel = gCloneChannel THEN\r\n\t\t\tfAuxView := view\r\n\t\tEND;\r\n\r\n\tPROCEDURE CleanUp (error: INTEGER; message: LONGINT);\r\n\r\n\t\tBEGIN\r\n\r\n\t\tIF rDataPtr &lt;&gt; NIL THEN fDoc.fData [0] . DoneWithPtr;\r\n\t\tIF gDataPtr &lt;&gt; NIL THEN fDoc.fData [1] . DoneWithPtr;\r\n\t\tIF bDataPtr &lt;&gt; NIL THEN fDoc.fData [2] . DoneWithPtr;\r\n\r\n\t\tIF dataPtr &lt;&gt; NIL THEN fDoc.fData [fChannel] . DoneWithPtr;\r\n\r\n\t\tRecoverFailure;\r\n\r\n\t\tFlushImage;\r\n\r\n\t\tmessage := fFailMessage;\r\n\r\n\t\tFree;\r\n\r\n\t\tFailure (error, message)\r\n\r\n\t\tEND;\r\n\r\n\tBEGIN\r\n\r\n\tTrackMouse := SELF;\r\n\r\n\tfView.TrackRulers;\r\n\r\n\tpt1 := previousPoint;\r\n\r\n\tIF aTrackPhase = TrackPress THEN\r\n\t\tBEGIN\r\n\r\n\t\tIF gEventInfo.theShiftKey AND (fLastPoint.h &gt;= 0) THEN\r\n\t\t\tBEGIN\r\n\t\t\tpt1 := fLastPoint;\r\n\t\t\tfView.CvtImage2View (pt1, kRoundDown)\r\n\t\t\tEND\r\n\r\n\t\tEND\r\n\r\n\tELSE IF aTrackPhase = TrackRelease THEN\r\n\t\tFixReleasePoint (anchorPoint, nextPoint);\r\n\r\n\tpt2 := nextPoint;\r\n\r\n\tmag := fView.fMagnification;\r\n\r\n\tIF mag &gt; 1 THEN\r\n\t\tBEGIN\r\n\t\tpt1.h := pt1.h DIV mag;\r\n\t\tpt1.v := pt1.v DIV mag;\r\n\t\tpt2.h := pt2.h DIV mag;\r\n\t\tpt2.v := pt2.v DIV mag\r\n\t\tEND\r\n\r\n\tELSE IF mag &lt; 1 THEN\r\n\t\tBEGIN\r\n\t\tmag := -mag;\r\n\t\tpt1.h := pt1.h * mag;\r\n\t\tpt1.v := pt1.v * mag;\r\n\t\tpt2.h := pt2.h * mag;\r\n\t\tpt2.v := pt2.v * mag\r\n\t\tEND;\r\n\r\n\tIF aTrackPhase = TrackPress THEN\r\n\t\tCASE fStampMethod OF\r\n\r\n\t\tkClone1Method,\r\n\t\tkClone2Method:\r\n\t\t\tBEGIN\r\n\r\n\t\t\tIF (gCloneTarget = fDoc) AND (fStampMethod = kClone1Method) THEN\r\n\t\t\t\tfStampOffset := gCloneOffset\r\n\r\n\t\t\tELSE\r\n\t\t\t\tBEGIN\r\n\r\n\t\t\t\tfStampOffset.h := gClonePoint.h - pt1.h;\r\n\t\t\t\tfStampOffset.v := gClonePoint.v - pt1.v;\r\n\r\n\t\t\t\tgCloneOffset := fStampOffset;\r\n\t\t\t\tgCloneTarget := fDoc\r\n\r\n\t\t\t\tEND;\r\n\r\n\t\t\tIF (gCloneDoc = fDoc) AND (gCloneChannel = fView.fChannel) THEN\r\n\t\t\t\tfAuxView := fView\r\n\t\t\tELSE\r\n\t\t\t\tgCloneDoc.fViewList.Each (FindAuxView)\r\n\r\n\t\t\tEND;\r\n\r\n\t\tkPattern2Method:\r\n\t\t\tBEGIN\r\n\t\t\tfStampOffset.h := pt1.h - BSR (gPatternRect.right -\r\n\t\t\t\t\t\t\t\t\t\t   gPatternRect.left, 1);\r\n\t\t\tfStampOffset.v := pt1.v - BSR (gPatternRect.bottom -\r\n\t\t\t\t\t\t\t\t\t\t   gPatternRect.top, 1)\r\n\t\t\tEND;\r\n\r\n\t\tkImpressMethod:\r\n\t\t\tBEGIN\r\n\t\t\tfImpressCounter := 0;\r\n\t\t\tfImpressTimer\t:= TickCount\r\n\t\t\tEND;\r\n\r\n\t\tOTHERWISE\r\n\t\t\tBEGIN\r\n\t\t\tfStampOffset.h := 0;\r\n\t\t\tfStampOffset.v := 0\r\n\t\t\tEND\r\n\r\n\t\tEND;\r\n\r\n\tIF fAuxView &lt;&gt; NIL THEN\r\n\t\tBEGIN\r\n\r\n\t\tauxPt.h := pt2.h + fStampOffset.h;\r\n\t\tauxPt.v := pt2.v + fStampOffset.v;\r\n\r\n\t\tgCloneDoc.GetBoundsRect (bounds);\r\n\r\n\t\tIF PtInRect (auxPt, bounds) THEN\r\n\t\t\tBEGIN\r\n\r\n\t\t\tfAuxView.CvtImage2View (auxPt, kRoundDown);\r\n\r\n\t\t\tauxMag := fAuxView.fMagnification;\r\n\r\n\t\t\tIF auxMag &gt; 1 THEN\r\n\t\t\t\tBEGIN\r\n\t\t\t\tauxMag := auxMag DIV 2;\r\n\t\t\t\tauxPt.h := auxPt.h + auxMag;\r\n\t\t\t\tauxPt.v := auxPt.v + auxMag\r\n\t\t\t\tEND;\r\n\r\n\t\t\t\tCASE aTrackPhase OF\r\n\r\n\t\t\t\tTrackPress:\r\n\t\t\t\t\tDrawAuxCursor (auxPt);\r\n\r\n\t\t\t\ttrackMove:\r\n\t\t\t\t\tIF NOT fAuxCursor THEN\r\n\t\t\t\t\t\tDrawAuxCursor (auxPt)\r\n\t\t\t\t\tELSE\r\n\t\t\t\t\t\tIF LONGINT (auxPt) &lt;&gt; LONGINT (fAuxLocation) THEN\r\n\t\t\t\t\t\t\tBEGIN\r\n\t\t\t\t\t\t\tDrawAuxCursor (fAuxLocation);\r\n\t\t\t\t\t\t\tDrawAuxCursor (auxPt)\r\n\t\t\t\t\t\t\tEND;\r\n\r\n\t\t\t\tTrackRelease:\r\n\t\t\t\t\tIF fAuxCursor THEN\r\n\t\t\t\t\t\tDrawAuxCursor (fAuxLocation)\r\n\r\n\t\t\t\tEND\r\n\r\n\t\t\tEND\r\n\r\n\t\tELSE IF fAuxCursor THEN\r\n\t\t\tDrawAuxCursor (fAuxLocation)\r\n\r\n\t\tEND;\r\n\r\n\trows := fDoc.fRows;\r\n\tcols := fDoc.fCols;\r\n\r\n\tdataPtr := NIL;\r\n\r\n\trDataPtr := NIL;\r\n\tgDataPtr := NIL;\r\n\tbDataPtr := NIL;\r\n\r\n\tCatchFailures (fi, CleanUp);\r\n\r\n\tIF fStampMethod = kImpressMethod THEN\r\n\t\tIF TickCount - fImpressTimer &gt;= 15 THEN\r\n\t\t\tBEGIN\r\n\t\t\tfImpressCounter := 0;\r\n\t\t\tfImpressTimer\t:= TickCount\r\n\t\t\tEND;\r\n\r\n\tIF (aTrackPhase = trackPress) OR (LONGINT (pt1) &lt;&gt; LONGINT (pt2)) THEN\r\n\t\tBEGIN\r\n\r\n\t\tIF (fSpacing = 0) AND (aTrackPhase &lt;&gt; trackPress) THEN\r\n\t\t\tMarkPoint (pt2)\r\n\t\tELSE\r\n\t\t\tInterpolatePoints (pt1, pt2, MarkPoint);\r\n\r\n\t\tFlushCache;\r\n\r\n\t\tfLastDrawTime := TickCount\r\n\r\n\t\tEND\r\n\r\n\tELSE IF (fDelay &gt; 0) AND (TickCount - fLastDrawTime &gt;= fDelay) THEN\r\n\t\tBEGIN\r\n\r\n\t\tfSpacingCounter := 1;\r\n\r\n\t\tMarkPoint (pt2);\r\n\r\n\t\tFlushCache;\r\n\r\n\t\tfLastDrawTime := TickCount\r\n\r\n\t\tEND;\r\n\r\n\tSuccess (fi);\r\n\r\n\tIF aTrackPhase = TrackRelease THEN FlushImage\r\n\r\n\tEND;\r\n\r\n{$IFC qTrace} {$D++} {$ENDC}\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TPencilTool.IPencilTool (view: TImageView; pt: Point);\r\n\r\n\tVAR\r\n\t\ttip: TTip;\r\n\t\tr: INTEGER;\r\n\t\tg: INTEGER;\r\n\t\tb: INTEGER;\r\n\t\tps: BOOLEAN;\r\n\t\tindex: INTEGER;\r\n\t\tpixels: INTEGER;\r\n\t\tmap: TLookUpTable;\r\n\t\tneedAlpha: BOOLEAN;\r\n\t\tdoc: TImageDocument;\r\n\r\n\tBEGIN\r\n\r\n\tfAutoErase := FALSE;\r\n\r\n\tdoc := TImageDocument (view.fDocument);\r\n\r\n\tLoadTip (tip, gPencilOptions.shapeID, view);\r\n\r\n\tpixels := tip.fSize.h * tip.fSize.v;\r\n\r\n\tIF gPencilOptions.check1 = 1 THEN\r\n\t\tBEGIN\r\n\r\n\t\tIF gEventInfo.theShiftKey &amp;\r\n\t\t   MEMBER (gLastCommand, TPencilTool) &amp;\r\n\t\t   (gLastCommand.fChangedDocument = doc) THEN\r\n\r\n\t\t\tfAutoErase := TPencilTool (gLastCommand) . fAutoErase\r\n\r\n\t\tELSE\r\n\t\t\tBEGIN\r\n\r\n\t\t\tview.GetViewColor (pt, r, g, b);\r\n\r\n\t\t\tIF view.fChannel = kRGBChannels THEN\r\n\t\t\t\tfAutoErase := (view.ForegroundByte (0) = r) &amp;\r\n\t\t\t\t\t\t\t  (view.ForegroundByte (1) = g) &amp;\r\n\t\t\t\t\t\t\t  (view.ForegroundByte (2) = b)\r\n\r\n\t\t\tELSE IF doc.fMode = IndexedColorMode THEN\r\n\t\t\t\tBEGIN\r\n\t\t\t\tindex := view.ForegroundByte (0);\r\n\t\t\t\tfAutoErase := (doc.fIndexedColorTable.R [index] = CHR (r)) &amp;\r\n\t\t\t\t\t\t\t  (doc.fIndexedColorTable.G [index] = CHR (g)) &amp;\r\n\t\t\t\t\t\t\t  (doc.fIndexedColorTable.B [index] = CHR (b))\r\n\t\t\t\tEND\r\n\r\n\t\t\tELSE\r\n\t\t\t\tfAutoErase := view.ForegroundByte (0) = r\r\n\r\n\t\t\tEND;\r\n\r\n\t\tIF fAutoErase THEN\r\n\t\t\tBEGIN\r\n\t\t\tDoSetBytes (tip.fData [1]^, pixels, view.BackgroundByte (0));\r\n\t\t\tIF tip.fData [2] &lt;&gt; NIL THEN\r\n\t\t\t\tBEGIN\r\n\t\t\t\tDoSetBytes (tip.fData [2]^, pixels, view.BackgroundByte (1));\r\n\t\t\t\tDoSetBytes (tip.fData [3]^, pixels, view.BackgroundByte (2))\r\n\t\t\t\tEND\r\n\t\t\tEND\r\n\r\n\t\tEND;\r\n\r\n\tps := (gPencilOptions.wacom = 1) &amp; UsingPressure;\r\n\r\n\tIF NOT ps THEN\r\n\t\tBEGIN\r\n\t\tmap [0] := CHR (0);\r\n\t\tDoSetBytes (@map [1], 255, 255);\r\n\t\tDoMapBytes (tip.fMask^, pixels, map)\r\n\t\tEND;\r\n\r\n\tneedAlpha := (gPencilOptions.pressure &lt;&gt; 100) AND\r\n\t\t\t\t (doc.fMode &lt;&gt; IndexedColorMode);\r\n\r\n\tIDrawingTool (view, cDrawing, tip, gPencilOptions.mode,\r\n\t\t\t\t\t\t\t\t\t   gPencilOptions.spacing,\r\n\t\t\t\t\t\t\t\t\t   \u06f0,\r\n\t\t\t\t\t\t\t\t\t   \u06f0,\r\n\t\t\t\t\t\t\t\t\t   msgCannotPencil,\r\n\t\t\t\t\t\t\t\t\t   needAlpha);\r\n\r\n\tIF needAlpha THEN\r\n\t\t{$H-}\r\n\t\tMakeRamp (fAlphaMap, gPencilOptions.pressure * 255 DIV 100);\r\n\t\t{$H+}\r\n\r\n\tIF ps THEN\r\n\t\tfPressureMode := 1\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nFUNCTION DoPencilTool (view: TImageView; pt: Point): TCommand;\r\n\r\n\tVAR\r\n\t\tfi: FailInfo;\r\n\t\taPencilTool: TPencilTool;\r\n\r\n\tPROCEDURE CleanUp (error: INTEGER; message: LONGINT);\r\n\t\tBEGIN\r\n\t\tFailNewMessage (error, message, msgCannotPencil)\r\n\t\tEND;\r\n\r\n\tBEGIN\r\n\r\n\tCatchFailures (fi, CleanUp);\r\n\r\n\tFailBadMode (view, FALSE, gPencilOptions.mode);\r\n\r\n\tNEW (aPencilTool);\r\n\tFailNil (aPencilTool);\r\n\r\n\taPencilTool.IPencilTool (view, pt);\r\n\r\n\tSuccess (fi);\r\n\r\n\tDoPencilTool := aPencilTool\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TBrushTool.IBrushTool (view: TImageView);\r\n\r\n\tVAR\r\n\t\ttip: TTip;\r\n\r\n\tBEGIN\r\n\r\n\tLoadTip (tip, gBrushOptions.shapeID, view);\r\n\r\n\tIDrawingTool (view, cPainting, tip, gBrushOptions.mode,\r\n\t\t\t\t\t\t\t\t\t\tgBrushOptions.spacing,\r\n\t\t\t\t\t\t\t\t\t\tgBrushOptions.fadeout,\r\n\t\t\t\t\t\t\t\t\t\tgBrushOptions.rate,\r\n\t\t\t\t\t\t\t\t\t\tmsgCannotBrush,\r\n\t\t\t\t\t\t\t\t\t\tgBrushOptions.pressure &lt;&gt; 100);\r\n\r\n\t{$H-}\r\n\tMakeRamp (fAlphaMap, gBrushOptions.pressure * 255 DIV 100);\r\n\t{$H+}\r\n\r\n\tIF (gBrushOptions.wacom = 1) &amp; UsingPressure THEN\r\n\t\tfPressureMode := 2\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nFUNCTION DoBrushTool (view: TImageView): TCommand;\r\n\r\n\tVAR\r\n\t\tfi: FailInfo;\r\n\t\taBrushTool: TBrushTool;\r\n\r\n\tPROCEDURE CleanUp (error: INTEGER; message: LONGINT);\r\n\t\tBEGIN\r\n\t\tFailNewMessage (error, message, msgCannotBrush)\r\n\t\tEND;\r\n\r\n\tBEGIN\r\n\r\n\tCatchFailures (fi, CleanUp);\r\n\r\n\tFailBadMode (view, TRUE, gBrushOptions.mode);\r\n\r\n\tNEW (aBrushTool);\r\n\tFailNil (aBrushTool);\r\n\r\n\taBrushTool.IBrushTool (view);\r\n\r\n\tSuccess (fi);\r\n\r\n\tDoBrushTool := aBrushTool\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TAirbrushTool.IAirbrushTool (view: TImageView);\r\n\r\n\tVAR\r\n\t\ttip: TTip;\r\n\t\tcross: LONGINT;\r\n\t\tweight: INTEGER;\r\n\t\tmap: TLookUpTable;\r\n\r\n\tBEGIN\r\n\r\n\tLoadTip (tip, gAirbrushOptions.shapeID, view);\r\n\r\n\tcross := TipCrossSection (tip);\r\n\r\n\tIF gAirbrushOptions.spacing &gt; 1 THEN\r\n\t\tcross := cross DIV Min (gAirbrushOptions.spacing, 5);\r\n\r\n\tcross := Min (Max (cross, 255), 2048);\r\n\r\n\tweight := ORD4 (255 * gAirbrushOptions.pressure DIV 100) * 255 DIV cross;\r\n\r\n\tIF weight &lt; 1 THEN weight := 1;\r\n\r\n\tMakeRamp (map, weight);\r\n\r\n\tDoMapBytes (tip.fMask^, tip.fSize.h * tip.fSize.v, map);\r\n\r\n\tIDrawingTool (view, cAirbrushing, tip, gAirbrushOptions.mode,\r\n\t\t\t\t\t\t\t\t\t\t   gAirbrushOptions.spacing,\r\n\t\t\t\t\t\t\t\t\t\t   gAirbrushOptions.fadeout,\r\n\t\t\t\t\t\t\t\t\t\t   gAirbrushOptions.rate,\r\n\t\t\t\t\t\t\t\t\t\t   msgCannotAirbrush,\r\n\t\t\t\t\t\t\t\t\t\t   FALSE);\r\n\r\n\tIF (gAirbrushOptions.wacom = 1) &amp; UsingPressure THEN\r\n\t\tfPressureMode := 3\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nFUNCTION DoAirbrushTool (view: TImageView): TCommand;\r\n\r\n\tVAR\r\n\t\tfi: FailInfo;\r\n\t\taAirbrushTool: TAirbrushTool;\r\n\r\n\tPROCEDURE CleanUp (error: INTEGER; message: LONGINT);\r\n\t\tBEGIN\r\n\t\tFailNewMessage (error, message, msgCannotAirbrush)\r\n\t\tEND;\r\n\r\n\tBEGIN\r\n\r\n\tCatchFailures (fi, CleanUp);\r\n\r\n\tFailBadMode (view, TRUE, gAirbrushOptions.mode);\r\n\r\n\tNEW (aAirbrushTool);\r\n\tFailNil (aAirbrushTool);\r\n\r\n\taAirbrushTool.IAirbrushTool (view);\r\n\r\n\tSuccess (fi);\r\n\r\n\tDoAirbrushTool := aAirbrushTool\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TBlurTool.IBlurTool (view: TImageView);\r\n\r\n\tVAR\r\n\t\ttip: TTip;\r\n\t\tmap: TLookUpTable;\r\n\r\n\tBEGIN\r\n\r\n\tLoadTip (tip, gBlurOptions.shapeID, view);\r\n\r\n\tMakeRamp (map, 255 * gBlurOptions.pressure DIV 100);\r\n\r\n\tDoMapBytes (tip.fMask^, tip.fSize.h * tip.fSize.v, map);\r\n\r\n\tIDrawingTool (view, cBlurring, tip, gBlurOptions.mode,\r\n\t\t\t\t\t\t\t\t\t\tgBlurOptions.spacing,\r\n\t\t\t\t\t\t\t\t\t\t\u06f0,\r\n\t\t\t\t\t\t\t\t\t\tgBlurOptions.rate,\r\n\t\t\t\t\t\t\t\t\t\tmsgCannotBlur,\r\n\t\t\t\t\t\t\t\t\t\tFALSE)\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nFUNCTION DoBlurTool (view: TImageView): TCommand;\r\n\r\n\tVAR\r\n\t\tfi: FailInfo;\r\n\t\taBlurTool: TBlurTool;\r\n\r\n\tPROCEDURE CleanUp (error: INTEGER; message: LONGINT);\r\n\t\tBEGIN\r\n\t\tFailNewMessage (error, message, msgCannotBlur)\r\n\t\tEND;\r\n\r\n\tBEGIN\r\n\r\n\tCatchFailures (fi, CleanUp);\r\n\r\n\tFailBadMode (view, TRUE, gBlurOptions.mode);\r\n\r\n\tNEW (aBlurTool);\r\n\tFailNil (aBlurTool);\r\n\r\n\taBlurTool.IBlurTool (view);\r\n\r\n\tSuccess (fi);\r\n\r\n\tDoBlurTool := aBlurTool\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TSharpenTool.ISharpenTool (view: TImageView);\r\n\r\n\tVAR\r\n\t\ttip: TTip;\r\n\t\tmap: TLookUpTable;\r\n\r\n\tBEGIN\r\n\r\n\tLoadTip (tip, gSharpenOptions.shapeID, view);\r\n\r\n\tMakeRamp (map, 255 * gSharpenOptions.pressure DIV 100);\r\n\r\n\tDoMapBytes (tip.fMask^, tip.fSize.h * tip.fSize.v, map);\r\n\r\n\tIDrawingTool (view, cSharpening, tip, gSharpenOptions.mode,\r\n\t\t\t\t\t\t\t\t\t\t  gSharpenOptions.spacing,\r\n\t\t\t\t\t\t\t\t\t\t  \u06f0,\r\n\t\t\t\t\t\t\t\t\t\t  gSharpenOptions.rate,\r\n\t\t\t\t\t\t\t\t\t\t  msgCannotSharpen,\r\n\t\t\t\t\t\t\t\t\t\t  FALSE)\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nFUNCTION DoSharpenTool (view: TImageView): TCommand;\r\n\r\n\tVAR\r\n\t\tfi: FailInfo;\r\n\t\taSharpenTool: TSharpenTool;\r\n\r\n\tPROCEDURE CleanUp (error: INTEGER; message: LONGINT);\r\n\t\tBEGIN\r\n\t\tFailNewMessage (error, message, msgCannotSharpen)\r\n\t\tEND;\r\n\r\n\tBEGIN\r\n\r\n\tCatchFailures (fi, CleanUp);\r\n\r\n\tFailBadMode (view, TRUE, gSharpenOptions.mode);\r\n\r\n\tNEW (aSharpenTool);\r\n\tFailNil (aSharpenTool);\r\n\r\n\taSharpenTool.ISharpenTool (view);\r\n\r\n\tSuccess (fi);\r\n\r\n\tDoSharpenTool := aSharpenTool\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TSmudgeTool.ISmudgeTool (view: TImageView; dip: BOOLEAN);\r\n\r\n\tVAR\r\n\t\ttip: TTip;\r\n\t\tgray: INTEGER;\r\n\t\tweight: LONGINT;\r\n\t\tmap: TLookUpTable;\r\n\r\n\tBEGIN\r\n\r\n\tLoadTip (tip, gSmudgeOptions.shapeID, view);\r\n\r\n\tIDrawingTool (view, cSmudging, tip, gSmudgeOptions.mode,\r\n\t\t\t\t\t\t\t\t\t\tgSmudgeOptions.spacing,\r\n\t\t\t\t\t\t\t\t\t\t\u06f0,\r\n\t\t\t\t\t\t\t\t\t\tgSmudgeOptions.rate,\r\n\t\t\t\t\t\t\t\t\t\tmsgCannotSmudge,\r\n\t\t\t\t\t\t\t\t\t\tFALSE);\r\n\r\n\tweight := 255 * gSmudgeOptions.pressure DIV 100;\r\n\r\n\tMakeRamp (map, weight);\r\n\r\n\tFOR gray := 0 TO 255 DO\r\n\t\tfMixMap [gray] := CHR (gray - ORD (map [gray]));\r\n\r\n\tIF weight &lt;&gt; 255 THEN\r\n\t\tFOR gray := 1 TO 255 DO\r\n\t\t\tIF fMixMap [gray] = CHR (0) THEN\r\n\t\t\t\tfMixMap [gray] := CHR (1);\r\n\r\n\tfDip := dip\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nFUNCTION DoSmudgeTool (view: TImageView; dip: BOOLEAN): TCommand;\r\n\r\n\tVAR\r\n\t\tfi: FailInfo;\r\n\t\taSmudgeTool: TSmudgeTool;\r\n\r\n\tPROCEDURE CleanUp (error: INTEGER; message: LONGINT);\r\n\t\tBEGIN\r\n\t\tFailNewMessage (error, message, msgCannotSmudge)\r\n\t\tEND;\r\n\r\n\tBEGIN\r\n\r\n\tCatchFailures (fi, CleanUp);\r\n\r\n\tFailBadMode (view, TRUE, gSmudgeOptions.mode);\r\n\r\n\tNEW (aSmudgeTool);\r\n\tFailNil (aSmudgeTool);\r\n\r\n\taSmudgeTool.ISmudgeTool (view, dip);\r\n\r\n\tSuccess (fi);\r\n\r\n\tDoSmudgeTool := aSmudgeTool\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TStampTool.IStampTool (view: TImageView; theMsg: LONGINT);\r\n\r\n\tVAR\r\n\t\ttip: TTip;\r\n\t\trate: INTEGER;\r\n\t\tpixels: INTEGER;\r\n\t\tmap: TLookUpTable;\r\n\t\titsCommand: INTEGER;\r\n\r\n\tBEGIN\r\n\r\n\tLoadTip (tip, gStampOptions.shapeID, view);\r\n\r\n\tpixels := tip.fSize.h * tip.fSize.v;\r\n\r\n\tIF gStampOptions.method = kTextureMethod THEN\r\n\t\tBEGIN\r\n\t\tmap [0] := CHR (0);\r\n\t\tDoSetBytes (@map [1], 255, 255);\r\n\t\tDoMapBytes (tip.fMask^, pixels, map)\r\n\t\tEND;\r\n\r\n\tIF (gStampOptions.method = kClone1Method) OR\r\n\t   (gStampOptions.method = kClone2Method) THEN\r\n\t\titsCommand := cCloning\r\n\tELSE IF gStampOptions.method = kRevertMethod THEN\r\n\t\titsCommand := cReverting\r\n\tELSE\r\n\t\titsCommand := cStamping;\r\n\r\n\tIF gStampOptions.method = kImpressMethod THEN\r\n\t\trate := 60\r\n\tELSE\r\n\t\trate := 0;\r\n\r\n\tIDrawingTool (view, itsCommand, tip, gStampOptions.mode,\r\n\t\t\t\t\t\t\t\t\t\t gStampOptions.spacing,\r\n\t\t\t\t\t\t\t\t\t\t \u06f0,\r\n\t\t\t\t\t\t\t\t\t\t rate,\r\n\t\t\t\t\t\t\t\t\t\t theMsg,\r\n\t\t\t\t\t\t\t\t\t\t gStampOptions.pressure &lt;&gt; 100);\r\n\r\n\t{$H-}\r\n\tMakeRamp (fAlphaMap, gStampOptions.pressure * 255 DIV 100);\r\n\t{$H+}\r\n\r\n\tfStampMethod := gStampOptions.method;\r\n\r\n\tIF fStampMethod = kTextureMethod THEN\r\n\t\tBEGIN\r\n\r\n\t\t{$IFC qBarneyscan}\r\n\t\tFailure (errNotYetImp, 0);\r\n\t\t{$ENDC}\r\n\r\n\t\tfTextureNoise := NewHandle (Max (256 + 16, pixels));\r\n\r\n\t\tMakeTextureNoise (fTextureNoise^, GetHandleSize (fTextureNoise))\r\n\r\n\t\tEND\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nFUNCTION DoStampTool (view: TImageView): TCommand;\r\n\r\n\tVAR\r\n\t\tfi: FailInfo;\r\n\t\ttheMsg: LONGINT;\r\n\t\taStampTool: TStampTool;\r\n\r\n\tPROCEDURE CleanUp (error: INTEGER; message: LONGINT);\r\n\t\tBEGIN\r\n\t\tFailNewMessage (error, message, theMsg)\r\n\t\tEND;\r\n\r\n\tBEGIN\r\n\r\n\t\tCASE gStampOptions.method OF\r\n\r\n\t\tkClone1Method,\r\n\t\tkClone2Method:\r\n\t\t\ttheMsg := msgCannotCloneStamp;\r\n\r\n\t\tkRevertMethod:\r\n\t\t\ttheMsg := msgCannotRevertStamp;\r\n\r\n\t\tkTextureMethod:\r\n\t\t\ttheMsg := msgCannotTextureStamp;\r\n\r\n\t\tkImpressMethod:\r\n\t\t\ttheMsg := msgCannotImpressStamp;\r\n\r\n\t\tOTHERWISE\r\n\t\t\ttheMsg := msgCannotPatternStamp\r\n\r\n\t\tEND;\r\n\r\n\tCatchFailures (fi, CleanUp);\r\n\r\n\tFailBadMode (view, TRUE, gStampOptions.mode);\r\n\r\n\t\tCASE gStampOptions.method OF\r\n\r\n\t\tkClone1Method,\r\n\t\tkClone2Method:\r\n\t\t\tBEGIN\r\n\r\n\t\t\tIF gCloneDoc = NIL THEN\r\n\t\t\t\tFailure (errNoCloneSource, 0);\r\n\r\n\t\t\tIF (gCloneChannel = kRGBChannels) AND\r\n\t\t\t   (gCloneDoc.fMode &lt;&gt; RGBColorMode) OR\r\n\t\t\t   (gCloneDoc.fMode = IndexedColorMode) OR\r\n\t\t\t   (gCloneDoc.fDepth &lt;&gt; 8) OR\r\n\t\t\t   (gCloneChannel &gt;= gCloneDoc.fChannels) OR\r\n\t\t\t   (gClonePoint.h &gt;= gCloneDoc.fCols) OR\r\n\t\t\t   (gClonePoint.v &gt;= gCloneDoc.fRows) THEN\r\n\t\t\t\tFailure (errNoCloneSource, 0)\r\n\r\n\t\t\tEND;\r\n\r\n\t\tkRevertMethod:\r\n\t\t\tGetMagicData (view, StampTool, TRUE);\r\n\r\n\t\tkTextureMethod:\r\n\t\t\tIF NOT gHaveTexture THEN\r\n\t\t\t\tFailure (errNoTexture, 0);\r\n\r\n\t\tkImpressMethod:\r\n\t\t\tGetMagicData (view, StampTool, FALSE);\r\n\r\n\t\tOTHERWISE\r\n\t\t\tIF EmptyRect (gPatternRect) THEN\r\n\t\t\t\tFailure (errNoPattern, 0)\r\n\r\n\t\tEND;\r\n\r\n\tNEW (aStampTool);\r\n\tFailNil (aStampTool);\r\n\r\n\taStampTool.IStampTool (view, theMsg);\r\n\r\n\tSuccess (fi);\r\n\r\n\tDoStampTool := aStampTool\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nFUNCTION DoStampPadTool (view: TImageView; pt: Point): TCommand;\r\n\r\n\tVAR\r\n\t\tfi: FailInfo;\r\n\t\tchannel: INTEGER;\r\n\t\tdoc: TImageDocument;\r\n\r\n\tPROCEDURE CleanUp (error: INTEGER; message: LONGINT);\r\n\t\tBEGIN\r\n\t\tFailNewMessage (error, message, msgCannotStamp)\r\n\t\tEND;\r\n\r\n\tPROCEDURE PickUpTexture (srcChannel: INTEGER; dstChannel: INTEGER);\r\n\r\n\t\tVAR\r\n\t\t\tr: Rect;\r\n\t\t\tsrcPtr: Ptr;\r\n\t\t\textra: INTEGER;\r\n\t\t\tpixels: INTEGER;\r\n\r\n\t\tBEGIN\r\n\r\n\t\tr.topLeft  := pt;\r\n\t\tr.botRight := pt;\r\n\r\n\t\tInsetRect (r, -8, -8);\r\n\r\n\t\tdoc.SectBoundsRect (r);\r\n\r\n\t\tsrcPtr := doc.fData [srcChannel] .\r\n\t\t\t\t  NeedPtr (r.top, r.bottom - 1, FALSE);\r\n\r\n\t\tDoGetTip (Ptr (ORD4 (srcPtr) + r.left),\r\n\t\t\t\t  @gTexture [dstChannel],\r\n\t\t\t\t  doc.fData [srcChannel] . fPhysicalSize,\r\n\t\t\t\t  r.right - r.left,\r\n\t\t\t\t  r.bottom - r.top,\r\n\t\t\t\t  r.right - r.left);\r\n\r\n\t\tdoc.fData [srcChannel] . DoneWithPtr;\r\n\t\tdoc.fData [srcChannel] . Flush;\r\n\r\n\t\tpixels := (r.right - r.left) * (r.bottom - r.top);\r\n\r\n\t\tWHILE pixels &lt; 256 DO\r\n\t\t\tBEGIN\r\n\r\n\t\t\textra := Min (256 - pixels, pixels);\r\n\r\n\t\t\tBlockMove (@gTexture [dstChannel],\r\n\t\t\t\t\t   @gTexture [dstChannel, pixels],\r\n\t\t\t\t\t   extra);\r\n\r\n\t\t\tpixels := pixels + extra\r\n\r\n\t\t\tEND\r\n\r\n\t\tEND;\r\n\r\n\tBEGIN\r\n\r\n\tdoc := TImageDocument (view.fDocument);\r\n\r\n\tview.CvtView2Image (pt);\r\n\r\n\tgCloneDoc\t  := doc;\r\n\tgCloneTarget  := NIL;\r\n\tgCloneChannel := view.fChannel;\r\n\tgClonePoint   := pt;\r\n\r\n\tCatchFailures (fi, CleanUp);\r\n\r\n\tFailBadMode (view, TRUE, NormalDrawing);\r\n\r\n\tgHaveTexture := FALSE;\r\n\r\n\tIF view.fChannel = kRGBChannels THEN\r\n\t\tBEGIN\r\n\r\n\t\tFOR channel := 0 TO 2 DO\r\n\t\t\tPickUpTexture (channel, channel + 1);\r\n\r\n\t\tDoMakeMonochrome (@gTexture [1], gGrayLUT.R,\r\n\t\t\t\t\t\t  @gTexture [2], gGrayLUT.G,\r\n\t\t\t\t\t\t  @gTexture [3], gGrayLUT.B,\r\n\t\t\t\t\t\t  @gTexture [0], 256)\r\n\r\n\t\tEND\r\n\r\n\tELSE\r\n\t\tBEGIN\r\n\r\n\t\tPickUpTexture (view.fChannel, 0);\r\n\r\n\t\tBlockMove (@gTexture [0], @gTexture [1], 256);\r\n\t\tBlockMove (@gTexture [0], @gTexture [2], 256);\r\n\t\tBlockMove (@gTexture [0], @gTexture [3], 256)\r\n\r\n\t\tEND;\r\n\r\n\tSuccess (fi);\r\n\r\n\tgHaveTexture := TRUE;\r\n\r\n\tIF (gStampOptions.method &lt;&gt; kClone1Method) AND\r\n\t   (gStampOptions.method &lt;&gt; kClone2Method) AND\r\n\t   (gStampOptions.method &lt;&gt; kTextureMethod) THEN\r\n\t\tgStampOptions.method := kClone1Method;\r\n\r\n\tDoStampPadTool := gNoChanges\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ASelCommand}\r\n\r\nPROCEDURE TEraseAll.IEraseAll (view: TImageView);\r\n\r\n\tBEGIN\r\n\r\n\tIBufferCommand (cEraseAll, view);\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TEraseAll.DoIt; OVERRIDE;\r\n\r\n\tVAR\r\n\t\tchannel: INTEGER;\r\n\t\taVMArray: TVMArray;\r\n\r\n\tBEGIN\r\n\r\n\tIF NOT EmptyRect (fDoc.fSelectionRect) THEN\r\n\t\tBEGIN\r\n\t\tfDoc.DeSelect (FALSE);\r\n\t\tfView.fFrame.ForceRedraw\r\n\t\tEND;\r\n\r\n\tfChannel := fView.fChannel;\r\n\r\n\tIF fChannel = kRGBChannels THEN\r\n\t\tFOR channel := 0 TO 2 DO\r\n\t\t\tBEGIN\r\n\r\n\t\t\taVMArray := NewVMArray (fDoc.fRows, fDoc.fCols, 3 - channel);\r\n\r\n\t\t\tfBuffer [channel] := aVMArray;\r\n\r\n\t\t\taVMArray.SetBytes (fView.BackgroundByte (channel))\r\n\r\n\t\t\tEND\r\n\r\n\tELSE\r\n\t\tBEGIN\r\n\r\n\t\taVMArray := NewVMArray (fDoc.fRows, fDoc.fCols, 1);\r\n\r\n\t\tfBuffer [0] := aVMArray;\r\n\r\n\t\taVMArray.SetBytes (fView.BackgroundByte (fChannel))\r\n\r\n\t\tEND;\r\n\r\n\tUndoIt\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TEraseAll.UndoIt; OVERRIDE;\r\n\r\n\tVAR\r\n\t\tchannel: INTEGER;\r\n\t\tsaveArray: TVMArray;\r\n\r\n\tPROCEDURE RedrawView (view: TImageView);\r\n\t\tBEGIN\r\n\r\n\t\tIF (fChannel = view.fChannel) OR\r\n\t\t   (fChannel = kRGBChannels) AND (view.fChannel &lt;= 2) OR\r\n\t\t   (fChannel &lt;= 2) AND (view.fChannel = kRGBChannels) THEN\r\n\r\n\t\t\tview.fFrame.ForceRedraw\r\n\r\n\t\tEND;\r\n\r\n\tBEGIN\r\n\r\n\tIF fChannel = kRGBChannels THEN\r\n\t\tFOR channel := 0 TO 2 DO\r\n\t\t\tBEGIN\r\n\t\t\tsaveArray\t\t\t := fDoc.fData [channel];\r\n\t\t\tfDoc.fData [channel] := fBuffer    [channel];\r\n\t\t\tfBuffer    [channel] := saveArray\r\n\t\t\tEND\r\n\tELSE\r\n\t\tBEGIN\r\n\t\tsaveArray\t\t\t  := fDoc.fData [fChannel];\r\n\t\tfDoc.fData [fChannel] := fBuffer\t[\u06f0\t\t ];\r\n\t\tfBuffer    [0\t\t] := saveArray\r\n\t\tEND;\r\n\r\n\tfDoc.fViewList.Each (RedrawView)\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ADoDraw}\r\n\r\nPROCEDURE TEraseAll.RedoIt; OVERRIDE;\r\n\r\n\tBEGIN\r\n\tUndoIt\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ASelCommand}\r\n\r\nFUNCTION DoEraseAll (view: TImageView): TCommand;\r\n\r\n\tVAR\r\n\t\tanEraseAll: TEraseAll;\r\n\r\n\tBEGIN\r\n\r\n\tIF TImageDocument (view.fDocument) . fDepth &lt;&gt; 8 THEN\r\n\t\tFailure (0, 0);\r\n\r\n\tNEW (anEraseAll);\r\n\tFailNil (anEraseAll);\r\n\r\n\tanEraseAll.IEraseAll (view);\r\n\r\n\tDoEraseAll := anEraseAll\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ARes3}\r\n\r\nFUNCTION BrushesVisible: BOOLEAN;\r\n\r\n\tBEGIN\r\n\r\n\tBrushesVisible := ORD (WindowPeek (gBrushesWindow.\r\n\t\t\t\t\t\t\t\t\t   fWmgrWindow)^.visible) &lt;&gt; 0\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ARes3}\r\n\r\nPROCEDURE ShowBrushes (visible: BOOLEAN);\r\n\r\n\tBEGIN\r\n\r\n\tgBrushesWindow.ShowGhost (visible)\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S AInit}\r\n\r\nPROCEDURE TBrushesView.IBrushesView;\r\n\r\n\tCONST\r\n\t\tkBrushesID = 1005;\r\n\r\n\tVAR\r\n\t\tr: Rect;\r\n\t\tlocation: Point;\r\n\r\n\tBEGIN\r\n\r\n\tfShapeID := -1;\r\n\r\n\tSetRect (r, 0, 0, 179, 105);\r\n\r\n\tIView (NIL, NIL, r, sizeFixed, sizeFixed, TRUE, HLOn);\r\n\r\n\t{$H-}\r\n\tSetRect (fCustomRect, 136, 65, 168, 97);\r\n\t{$H+}\r\n\r\n\tgBrushesWindow := TGhostWindow (NewGhostWindow (kBrushesID, SELF));\r\n\r\n\tSetPort (gBrushesWindow.fWmgrWindow);\r\n\r\n\tlocation.v := screenBits.bounds.bottom;\r\n\tlocation.h := screenBits.bounds.right;\r\n\r\n\tLocalToGlobal (location);\r\n\r\n\tMoveWindow (gBrushesWindow.fWmgrWindow, -30000, -30000, FALSE);\r\n\r\n\tgBrushesWindow.Open;\r\n\r\n\tgBrushesWindow.ShowGhost (FALSE);\r\n\r\n\tMoveWindow (gBrushesWindow.fWmgrWindow, location.h, location.v, FALSE)\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ARes3}\r\n\r\nPROCEDURE TBrushesView.HighlightShape (turnOn: BOOLEAN);\r\n\r\n\tVAR\r\n\t\tr: Rect;\r\n\t\trow: INTEGER;\r\n\t\tcol: INTEGER;\r\n\r\n\tBEGIN\r\n\r\n\tIF fShapeID &lt; 0 THEN\r\n\t\tEXIT (HighlightShape);\r\n\r\n\tIF fShapeID = 0 THEN\r\n\t\tBEGIN\r\n\r\n\t\trow := 2;\r\n\t\tcol := 5;\r\n\r\n\t\tSetRect (r, 0, 0, 2 * kTipSize, 2 * kTipSize)\r\n\r\n\t\tEND\r\n\r\n\tELSE\r\n\t\tBEGIN\r\n\r\n\t\tIF fShapeID &lt;= 19 THEN\r\n\t\t\tBEGIN\r\n\t\t\trow := (fShapeID - 1) DIV 7;\r\n\t\t\tcol := (fShapeID - 1) MOD 7\r\n\t\t\tEND\r\n\t\tELSE\r\n\t\t\tBEGIN\r\n\t\t\trow := 3;\r\n\t\t\tcol := fShapeID - 20\r\n\t\t\tEND;\r\n\r\n\t\tSetRect (r, 0, 0, kTipSize, kTipSize)\r\n\r\n\t\tEND;\r\n\r\n\tOffsetRect (r, 2 + kTipSize * col,\r\n\t\t\t\t   \u06f2 + kTipSize * row);\r\n\r\n\tPenNormal;\r\n\r\n\tIF NOT turnOn THEN PenPat (white);\r\n\r\n\tPenSize (2, 2);\r\n\r\n\tFrameRect (r);\r\n\r\n\tPenNormal\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S AToolOptions}\r\n\r\nFUNCTION TBrushesView.DoMouseCommand\r\n\t\t(VAR downLocalPoint: Point;\r\n\t\t VAR info: EventInfo;\r\n\t\t VAR hysteresis: Point): TCommand; OVERRIDE;\r\n\r\n\tVAR\r\n\t\tr: Rect;\r\n\t\tpt: Point;\r\n\t\tpick: INTEGER;\r\n\r\n\tBEGIN\r\n\r\n\tDoMouseCommand := gNoChanges;\r\n\r\n\tr := fExtentRect;\r\n\r\n\tInsetRect (r, 2, 2);\r\n\r\n\tIF PtInRect (downLocalPoint, r) THEN\r\n\t\tBEGIN\r\n\r\n\t\tpt.v := downLocalPoint.v - r.top;\r\n\t\tpt.h := downLocalPoint.h - r.left;\r\n\r\n\t\tpick := (pt.v DIV kTipSize) * 7 +\r\n\t\t\t\t(pt.h DIV kTipSize) + 1;\r\n\r\n\t\tIF (pick = 20) OR (pick = 21) OR (pick &gt;= 27) THEN\r\n\t\t\tpick := 0\r\n\t\tELSE IF pick &gt;= 22 THEN\r\n\t\t\tpick := pick - 2;\r\n\r\n\t\tIF (pick &lt;&gt; fShapeID) AND (fShapeID &lt;&gt; -1) THEN\r\n\t\t\tBEGIN\r\n\r\n\t\t\tHighlightShape (FALSE);\r\n\t\t\tfShapeID := pick;\r\n\t\t\tHighlightShape (TRUE);\r\n\r\n\t\t\t\tCASE gTool OF\r\n\r\n\t\t\t\tPencilTool:\r\n\t\t\t\t\tgPencilOptions.shapeID := pick;\r\n\r\n\t\t\t\tBrushTool:\r\n\t\t\t\t\tgBrushOptions.shapeID := pick;\r\n\r\n\t\t\t\tAirbrushTool:\r\n\t\t\t\t\tgAirbrushOptions.shapeID := pick;\r\n\r\n\t\t\t\tStampTool:\r\n\t\t\t\t\tgStampOptions.shapeID := pick;\r\n\r\n\t\t\t\tSmudgeTool:\r\n\t\t\t\t\tgSmudgeOptions.shapeID := pick;\r\n\r\n\t\t\t\tBlurTool:\r\n\t\t\t\t\tgBlurOptions.shapeID := pick;\r\n\r\n\t\t\t\tSharpenTool:\r\n\t\t\t\t\tgSharpenOptions.shapeID := pick\r\n\r\n\t\t\t\tEND\r\n\r\n\t\t\tEND\r\n\r\n\t\tEND\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ARes3}\r\n\r\nPROCEDURE TBrushesView.Draw (area: Rect); OVERRIDE;\r\n\r\n\tVAR\r\n\t\tr: Rect;\r\n\t\tpict: PicHandle;\r\n\r\n\tBEGIN\r\n\r\n\tpict := GetPicture (kShapesPictID);\r\n\r\n\tIF pict &lt;&gt; NIL THEN\r\n\t\tBEGIN\r\n\t\tHLock (Handle (pict));\r\n\t\tr := fExtentRect;\r\n\t\tInsetRect (r, -1, -1);\r\n\t\tDrawPicture (pict, r);\r\n\t\tHUnlock (Handle (pict))\r\n\t\tEND;\r\n\r\n\tIF gCustomSize.h &lt;&gt; 0 THEN\r\n\t\tBEGIN\r\n\t\tr := fCustomRect;\r\n\t\tPlotIcon (r, gCustomIcon)\r\n\t\tEND;\r\n\r\n\tHighlightShape (TRUE)\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S ARes3}\r\n\r\nPROCEDURE UpdateBrush;\r\n\r\n\tVAR\r\n\t\tshape: INTEGER;\r\n\r\n\tBEGIN\r\n\r\n\t\tCASE gTool OF\r\n\r\n\t\tPencilTool:\r\n\t\t\tshape := gPencilOptions.shapeID;\r\n\r\n\t\tBrushTool:\r\n\t\t\tshape := gBrushOptions.shapeID;\r\n\r\n\t\tAirbrushTool:\r\n\t\t\tshape := gAirbrushOptions.shapeID;\r\n\r\n\t\tStampTool:\r\n\t\t\tshape := gStampOptions.shapeID;\r\n\r\n\t\tSmudgeTool:\r\n\t\t\tshape := gSmudgeOptions.shapeID;\r\n\r\n\t\tBlurTool:\r\n\t\t\tshape := gBlurOptions.shapeID;\r\n\r\n\t\tSharpenTool:\r\n\t\t\tshape := gSharpenOptions.shapeID;\r\n\r\n\t\tOTHERWISE\r\n\t\t\tshape := -1\r\n\r\n\t\tEND;\r\n\r\n\tIF shape &lt;&gt; gBrushesView.fShapeID THEN\r\n\t\tBEGIN\r\n\t\tgBrushesView.fFrame.Focus;\r\n\t\tgBrushesView.HighlightShape (FALSE);\r\n\t\tgBrushesView.fShapeID := shape;\r\n\t\tgBrushesView.HighlightShape (TRUE)\r\n\t\tEND\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S AToolOptions}\r\n\r\nPROCEDURE TShapeDialog.IShapeDialog (dialogID, shapeID: INTEGER);\r\n\r\n\tCONST\r\n\t\tkHookItem\t= \u06f3;\r\n\t\tkShapesItem = 4;\r\n\t\tkCustomItem = 5;\r\n\r\n\tVAR\r\n\t\tr: Rect;\r\n\t\titemType: INTEGER;\r\n\t\titemHandle: Handle;\r\n\r\n\tBEGIN\r\n\r\n\tfShapeID := shapeID;\r\n\r\n\tIBWDialog (dialogID, kHookItem, ok);\r\n\r\n\tGetDItem (fDialogPtr, kShapesItem, itemType, itemHandle, r);\r\n\r\n\tInsetRect (r, 3, 3);\r\n\r\n\tfShapesRect := r;\r\n\r\n\tGetDItem (fDialogPtr, kCustomItem, itemType, itemHandle, r);\r\n\r\n\tfCustomRect := r\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S AToolOptions}\r\n\r\nPROCEDURE TShapeDialog.HighlightShape (turnOn: BOOLEAN);\r\n\r\n\tVAR\r\n\t\tr: Rect;\r\n\t\trow: INTEGER;\r\n\t\tcol: INTEGER;\r\n\r\n\tBEGIN\r\n\r\n\tIF fShapeID = 0 THEN\r\n\t\tBEGIN\r\n\r\n\t\trow := 2;\r\n\t\tcol := 5;\r\n\r\n\t\tSetRect (r, 0, 0, 2 * kTipSize, 2 * kTipSize)\r\n\r\n\t\tEND\r\n\r\n\tELSE\r\n\t\tBEGIN\r\n\r\n\t\tIF fShapeID &lt;= 19 THEN\r\n\t\t\tBEGIN\r\n\t\t\trow := (fShapeID - 1) DIV 7;\r\n\t\t\tcol := (fShapeID - 1) MOD 7\r\n\t\t\tEND\r\n\t\tELSE\r\n\t\t\tBEGIN\r\n\t\t\trow := 3;\r\n\t\t\tcol := fShapeID - 20\r\n\t\t\tEND;\r\n\r\n\t\tSetRect (r, 0, 0, kTipSize, kTipSize)\r\n\r\n\t\tEND;\r\n\r\n\tOffsetRect (r, fShapesRect.left + kTipSize * col,\r\n\t\t\t\t   fShapesRect.top\t+ kTipSize * row);\r\n\r\n\tPenNormal;\r\n\r\n\tIF NOT turnOn THEN PenPat (white);\r\n\r\n\tPenSize (2, 2);\r\n\r\n\tFrameRect (r);\r\n\r\n\tPenNormal\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S AToolOptions}\r\n\r\nPROCEDURE TShapeDialog.DrawAmendments (theItem: INTEGER); OVERRIDE;\r\n\r\n\tVAR\r\n\t\tr: Rect;\r\n\t\tpict: PicHandle;\r\n\r\n\tBEGIN\r\n\r\n\tINHERITED DrawAmendments (theItem);\r\n\r\n\tr := fShapesRect;\r\n\tInsetRect (r, -3, -3);\r\n\r\n\tpict := GetPicture (kShapesPictID);\r\n\r\n\tIF pict &lt;&gt; NIL THEN\r\n\t\tBEGIN\r\n\t\tHLock (Handle (pict));\r\n\t\tDrawPicture (pict, r);\r\n\t\tHUnlock (Handle (pict))\r\n\t\tEND;\r\n\r\n\tIF gCustomSize.h &lt;&gt; 0 THEN\r\n\t\tBEGIN\r\n\t\tr := fCustomRect;\r\n\t\tPlotIcon (r, gCustomIcon)\r\n\t\tEND;\r\n\r\n\tHighlightShape (TRUE)\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S AToolOptions}\r\n\r\nPROCEDURE TShapeDialog.DoFilterEvent (VAR anEvent: EventRecord;\r\n\t\t\t\t\t\t\t\t\t  VAR itemHit: INTEGER;\r\n\t\t\t\t\t\t\t\t\t  VAR handledIt: BOOLEAN;\r\n\t\t\t\t\t\t\t\t\t  VAR doReturn: BOOLEAN); OVERRIDE;\r\n\r\n\tVAR\r\n\t\tpt: Point;\r\n\t\tpick: INTEGER;\r\n\t\twhichWindow: WindowPtr;\r\n\r\n\tBEGIN\r\n\r\n\tIF anEvent.what = mouseDown THEN\r\n\t\tIF FindWindow (anEvent.where, whichWindow) = inContent THEN\r\n\t\t\tIF whichWindow = fDialogPtr THEN\r\n\t\t\t\tBEGIN\r\n\r\n\t\t\t\tSetPort (fDialogPtr);\r\n\r\n\t\t\t\tpt := anEvent.where;\r\n\t\t\t\tGlobalToLocal (pt);\r\n\r\n\t\t\t\tIF PtInRect (pt, fShapesRect) THEN\r\n\t\t\t\t\tBEGIN\r\n\r\n\t\t\t\t\tpt.v := pt.v - fShapesRect.top;\r\n\t\t\t\t\tpt.h := pt.h - fShapesRect.left;\r\n\r\n\t\t\t\t\tpick := (pt.v DIV kTipSize) * 7 +\r\n\t\t\t\t\t\t\t(pt.h DIV kTipSize) + 1;\r\n\r\n\t\t\t\t\tIF (pick = 20) OR (pick = 21) OR (pick &gt;= 27) THEN\r\n\t\t\t\t\t\tpick := 0\r\n\t\t\t\t\tELSE IF pick &gt;= 22 THEN\r\n\t\t\t\t\t\tpick := pick - 2;\r\n\r\n\t\t\t\t\t{$IFC qBarneyscan}\r\n\t\t\t\t\tIF pick = 0 THEN\r\n\t\t\t\t\t\tpick := fShapeID;\r\n\t\t\t\t\t{$ENDC}\r\n\r\n\t\t\t\t\tIF pick &lt;&gt; fShapeID THEN\r\n\t\t\t\t\t\tBEGIN\r\n\t\t\t\t\t\tHighlightShape (FALSE);\r\n\t\t\t\t\t\tfShapeID := pick;\r\n\t\t\t\t\t\tHighlightShape (TRUE)\r\n\t\t\t\t\t\tEND;\r\n\r\n\t\t\t\t\tanEvent.what := nullEvent\r\n\r\n\t\t\t\t\tEND\r\n\r\n\t\t\t\tEND;\r\n\r\n\tINHERITED DoFilterEvent (anEvent, itemHit, handledIt, doReturn)\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S AToolOptions}\r\n\r\nPROCEDURE DoToolOptions (dialogID: INTEGER; VAR options: TToolOptions);\r\n\r\n\tCONST\r\n\t\tkFirstModeItem = 6;\r\n\t\tkLastModeItem  = 9;\r\n\t\tkFirstEditItem = 10;\r\n\r\n\tVAR\r\n\t\tfi: FailInfo;\r\n\t\titem: INTEGER;\r\n\t\titemBox: Rect;\r\n\t\titemType: INTEGER;\r\n\t\titemHandle: Handle;\r\n\t\tdoc: TImageDocument;\r\n\t\trateText: TFixedText;\r\n\t\tcheckbox1: TCheckBox;\r\n\t\tcheckbox2: TCheckBox;\r\n\t\tspacingText: TFixedText;\r\n\t\tfadeoutText: TFixedText;\r\n\t\tpressureText: TFixedText;\r\n\t\tmodeCluster: TRadioCluster;\r\n\t\taShapeDialog: TShapeDialog;\r\n\t\tmethodCluster: TRadioCluster;\r\n\r\n\tPROCEDURE CleanUp (error: INTEGER; message: LONGINT);\r\n\t\tBEGIN\r\n\t\taShapeDialog.Free\r\n\t\tEND;\r\n\r\n\tBEGIN\r\n\r\n\tNEW (aShapeDialog);\r\n\tFailNil (aShapeDialog);\r\n\r\n\taShapeDialog.IShapeDialog (dialogID, options.shapeID);\r\n\r\n\tCatchFailures (fi, CleanUp);\r\n\r\n\tmodeCluster := aShapeDialog.DefineRadioCluster\r\n\t\t\t(kFirstModeItem, kLastModeItem,\r\n\t\t\t kFirstModeItem + ORD (options.mode));\r\n\r\n\titem := kFirstEditItem;\r\n\r\n\tspacingText := aShapeDialog.DefineFixedText\r\n\t\t\t\t   (item, 0, FALSE, TRUE, 0, 999);\r\n\r\n\tspacingText.StuffValue (options.spacing);\r\n\r\n\titem := item + 1;\r\n\r\n\tIF options.fadeout &lt;&gt; kUndefinedOption THEN\r\n\t\tBEGIN\r\n\r\n\t\tfadeoutText := aShapeDialog.DefineFixedText\r\n\t\t\t\t\t   (item, 0, TRUE, TRUE, -999, 999);\r\n\r\n\t\tIF options.fadeout &lt;&gt; 0 THEN\r\n\t\t\tfadeoutText.StuffValue (options.fadeout);\r\n\r\n\t\titem := item + 1\r\n\r\n\t\tEND;\r\n\r\n\tIF options.rate &lt;&gt; kUndefinedOption THEN\r\n\t\tBEGIN\r\n\r\n\t\trateText := aShapeDialog.DefineFixedText\r\n\t\t\t\t\t(item, 0, TRUE, TRUE, 0, 60);\r\n\r\n\t\tIF options.rate &lt;&gt; 0 THEN\r\n\t\t\trateText.StuffValue (options.rate);\r\n\r\n\t\titem := item + 1\r\n\r\n\t\tEND;\r\n\r\n\tIF options.pressure &lt;&gt; kUndefinedOption THEN\r\n\t\tBEGIN\r\n\r\n\t\tpressureText := aShapeDialog.DefineFixedText\r\n\t\t\t\t\t\t(item, 0, FALSE, TRUE, 1, 100);\r\n\r\n\t\tpressureText.StuffValue (options.pressure);\r\n\r\n\t\taShapeDialog.SetEditSelection (item);\r\n\r\n\t\titem := item + 1\r\n\r\n\t\tEND\r\n\r\n\tELSE\r\n\t\taShapeDialog.SetEditSelection (kFirstEditItem);\r\n\r\n\tIF options.method &lt;&gt; kUndefinedOption THEN\r\n\t\tBEGIN\r\n\r\n\t\tmethodCluster := aShapeDialog.DefineRadioCluster\r\n\t\t\t\t\t\t (item, item + 6, item + options.method);\r\n\r\n\t\titem := item + 7\r\n\r\n\t\tEND;\r\n\r\n\tIF options.check1 &lt;&gt; kUndefinedOption THEN\r\n\t\tBEGIN\r\n\t\tcheckbox1 := aShapeDialog.DefineCheckBox (item, options.check1 = 1);\r\n\t\titem := item + 1\r\n\t\tEND;\r\n\r\n\tIF options.wacom &lt;&gt; kUndefinedOption THEN\r\n\t\tBEGIN\r\n\t\tcheckbox2 := aShapeDialog.DefineCheckBox (item, options.wacom = 1);\r\n\t\tIF NOT gHavePressure THEN\r\n\t\t\tHideControl (ControlHandle (checkbox2.fItemHandle))\r\n\t\tEND;\r\n\r\n\taShapeDialog.TalkToUser (item, StdItemHandling);\r\n\r\n\tIF item &lt;&gt; ok THEN Failure (0, 0);\r\n\r\n\toptions.shapeID := aShapeDialog.fShapeID;\r\n\r\n\toptions.mode := TDrawingMode (modeCluster.fChosenItem - kFirstModeItem);\r\n\r\n\toptions.spacing := spacingText.fValue;\r\n\r\n\tIF options.fadeout &lt;&gt; kUndefinedOption THEN\r\n\t\toptions.fadeout := fadeoutText.fValue;\r\n\r\n\tIF options.rate &lt;&gt; kUndefinedOption THEN\r\n\t\toptions.rate := rateText.fValue;\r\n\r\n\tIF options.pressure &lt;&gt; kUndefinedOption THEN\r\n\t\toptions.pressure := pressureText.fValue;\r\n\r\n\tIF options.method &lt;&gt; kUndefinedOption THEN\r\n\t\toptions.method := methodCluster.fChosenItem -\r\n\t\t\t\t\t\t  methodCluster.fFirstItem;\r\n\r\n\tIF options.check1 &lt;&gt; kUndefinedOption THEN\r\n\t\toptions.check1 := ORD (checkbox1.fChecked);\r\n\r\n\tIF options.wacom &lt;&gt; kUndefinedOption THEN\r\n\t\toptions.wacom := ORD (checkbox2.fChecked);\r\n\r\n\tSuccess (fi);\r\n\r\n\tCleanUp (0, 0);\r\n\r\n\tUpdateBrush\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S AToolOptions}\r\n\r\nPROCEDURE DoPencilOptions;\r\n\r\n\tCONST\r\n\t\tkDialogID = 1082;\r\n\r\n\tBEGIN\r\n\tDoToolOptions (kDialogID, gPencilOptions)\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S AToolOptions}\r\n\r\nPROCEDURE DoBrushOptions;\r\n\r\n\tCONST\r\n\t\tkDialogID = 1083;\r\n\r\n\tBEGIN\r\n\tDoToolOptions (kDialogID, gBrushOptions)\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S AToolOptions}\r\n\r\nPROCEDURE DoAirbrushOptions;\r\n\r\n\tCONST\r\n\t\tkDialogID = 1084;\r\n\r\n\tBEGIN\r\n\tDoToolOptions (kDialogID, gAirbrushOptions)\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S AToolOptions}\r\n\r\nPROCEDURE DoBlurOptions;\r\n\r\n\tCONST\r\n\t\tkDialogID = 1085;\r\n\r\n\tBEGIN\r\n\tDoToolOptions (kDialogID, gBlurOptions)\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S AToolOptions}\r\n\r\nPROCEDURE DoSharpenOptions;\r\n\r\n\tCONST\r\n\t\tkDialogID = 1086;\r\n\r\n\tBEGIN\r\n\tDoToolOptions (kDialogID, gSharpenOptions)\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S AToolOptions}\r\n\r\nPROCEDURE DoSmudgeOptions;\r\n\r\n\tCONST\r\n\t\tkDialogID = 1087;\r\n\r\n\tBEGIN\r\n\tDoToolOptions (kDialogID, gSmudgeOptions)\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S AToolOptions}\r\n\r\nPROCEDURE DoStampOptions;\r\n\r\n\tCONST\r\n\t\tkDialogID = 1088;\r\n\r\n\tBEGIN\r\n\tDoToolOptions (kDialogID, gStampOptions);\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S AToolOptions}\r\n\r\nPROCEDURE DefineBrush (view: TImageView);\r\n\r\n\tVAR\r\n\t\tr: Rect;\r\n\t\trr: Rect;\r\n\t\tj: INTEGER;\r\n\t\tk: INTEGER;\r\n\t\tjj: INTEGER;\r\n\t\tkk: INTEGER;\r\n\t\tsrcPtr: Ptr;\r\n\t\tdstPtr: Ptr;\r\n\t\tfi: FailInfo;\r\n\t\toffset: Point;\r\n\t\tmap: TLookUpTable;\r\n\t\tdoc: TImageDocument;\r\n\t\tbuffer: ARRAY [0..3] OF TVMArray;\r\n\r\n\tPROCEDURE CleanUp (error: INTEGER; message: LONGINT);\r\n\t\tBEGIN\r\n\t\tFreeObject (buffer [0]);\r\n\t\tFreeObject (buffer [1]);\r\n\t\tFreeObject (buffer [2]);\r\n\t\tFreeObject (buffer [3]);\r\n\t\tEND;\r\n\r\n\tBEGIN\r\n\r\n\tMoveHands (TRUE);\r\n\r\n\tbuffer [0] := NIL;\r\n\tbuffer [1] := NIL;\r\n\tbuffer [2] := NIL;\r\n\tbuffer [3] := NIL;\r\n\r\n\tCatchFailures (fi, CleanUp);\r\n\r\n\tdoc := TImageDocument (view.fDocument);\r\n\r\n\tr := doc.fSelectionRect;\r\n\r\n\tIF view.fChannel = kRGBChannels THEN\r\n\t\tBEGIN\r\n\r\n\t\tFOR j := 1 TO 3 DO\r\n\t\t\tBEGIN\r\n\t\t\tMoveHands (TRUE);\r\n\t\t\tbuffer [j] := doc.fData [j - 1] . CopyRect (r, 1)\r\n\t\t\tEND;\r\n\r\n\t\tMoveHands (TRUE);\r\n\r\n\t\tbuffer [0] := MakeMonochromeArray (buffer [1],\r\n\t\t\t\t\t\t\t\t\t\t   buffer [2],\r\n\t\t\t\t\t\t\t\t\t\t   buffer [3]);\r\n\r\n\t\tFOR j := 1 TO 3 DO\r\n\t\t\tBEGIN\r\n\t\t\tbuffer [j] . Free;\r\n\t\t\tbuffer [j] := NIL\r\n\t\t\tEND\r\n\r\n\t\tEND\r\n\r\n\tELSE\r\n\t\tBEGIN\r\n\r\n\t\tbuffer [0] := doc.fData [view.fChannel] . CopyRect (r, 1);\r\n\r\n\t\tMoveHands (TRUE);\r\n\r\n\t\tIF doc.fMode = IndexedColorMode THEN\r\n\t\t\tBEGIN\r\n\r\n\t\t\tFOR j := 0 TO 255 DO\r\n\t\t\t\tmap [j] := ConvertToGray (doc.fIndexedColorTable.R [j],\r\n\t\t\t\t\t\t\t\t\t\t  doc.fIndexedColorTable.G [j],\r\n\t\t\t\t\t\t\t\t\t\t  doc.fIndexedColorTable.B [j]);\r\n\r\n\t\t\tbuffer [0] . MapBytes (map)\r\n\r\n\t\t\tEND\r\n\r\n\t\tEND;\r\n\r\n\tMoveHands (TRUE);\r\n\tbuffer [0] . MapBytes (gInvertLUT);\r\n\r\n\tMoveHands (TRUE);\r\n\tbuffer [0] . FindBounds (r);\r\n\r\n\tIF (r.right - r.left &gt; kMaxTipSize) OR\r\n\t   (r.bottom - r.top &gt; kMaxTipSize) THEN Failure (errBrushTooLarge, 0);\r\n\r\n\tgCustomSize := Point (0);\r\n\r\n\trr := gBrushesView.fCustomRect;\r\n\tgBrushesView.fFrame.InvalidRect (rr);\r\n\r\n\tFOR j := r.top TO r.bottom - 1 DO\r\n\t\tBEGIN\r\n\t\tBlockMove (Ptr (ORD4 (buffer [0] . NeedPtr (j, j, FALSE)) + r.left),\r\n\t\t\t\t   @gCustomTip [(r.right - r.left) * (j - r.top)],\r\n\t\t\t\t   r.right - r.left);\r\n\t\tbuffer [0] . DoneWithPtr\r\n\t\tEND;\r\n\r\n\tgCustomSize.h := r.right - r.left;\r\n\tgCustomSize.v := r.bottom - r.top;\r\n\r\n\tbuffer [0] . Free;\r\n\tbuffer [0] := NIL;\r\n\r\n\tDoSetBytes (gCustomIcon^, 128, 0);\r\n\r\n\toffset.v := Max (0, (32 - gCustomSize.v) DIV 2);\r\n\toffset.h := Max (0, (32 - gCustomSize.h) DIV 2);\r\n\r\n\tFOR j := 0 TO gCustomSize.v - 1 DO\r\n\t\tBEGIN\r\n\r\n\t\tjj := j + offset.v;\r\n\r\n\t\tIF jj &lt;= 31 THEN\r\n\t\t\tBEGIN\r\n\r\n\t\t\tsrcPtr := @gCustomTip [j * gCustomSize.h];\r\n\t\t\tdstPtr := Ptr (ORD4 (gCustomIcon^) + jj * 4);\r\n\r\n\t\t\tFOR k := 0 TO gCustomSize.h - 1 DO\r\n\t\t\t\tBEGIN\r\n\r\n\t\t\t\tkk := k + offset.h;\r\n\r\n\t\t\t\tIF (kk &lt;= 31) &amp; (srcPtr^ &lt;&gt; 0) THEN\r\n\t\t\t\t\tBitSet (dstPtr, kk);\r\n\r\n\t\t\t\tsrcPtr := Ptr (ORD4 (srcPtr) + 1)\r\n\r\n\t\t\t\tEND\r\n\r\n\t\t\tEND\r\n\r\n\t\tEND;\r\n\r\n\tdoc.DeSelect (TRUE);\r\n\r\n\tSuccess (fi)\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S AToolOptions}\r\n\r\nPROCEDURE CopyPatternBand (srcArray: TVMArray;\r\n\t\t\t\t\t\t   dstArray: TVMArray;\r\n\t\t\t\t\t\t   r: Rect);\r\n\r\n\tVAR\r\n\t\tp: Ptr;\r\n\t\trr: Rect;\r\n\t\trow: INTEGER;\r\n\r\n\tBEGIN\r\n\r\n\trr := gPatternRect;\r\n\r\n\tsrcArray.MoveRect (dstArray, r, rr);\r\n\r\n\tFOR row := rr.top TO rr.bottom - 1 DO\r\n\t\tBEGIN\r\n\r\n\t\tp := dstArray.NeedPtr (row, row, TRUE);\r\n\r\n\t\tDoCopyForward (Ptr (ORD4 (p) + rr.left),\r\n\t\t\t\t\t   Ptr (ORD4 (p) + rr.right),\r\n\t\t\t\t\t   rr.left);\r\n\r\n\t\tDoCopyBackward (Ptr (ORD4 (p) + rr.right),\r\n\t\t\t\t\t\tPtr (ORD4 (p) + rr.left),\r\n\t\t\t\t\t\trr.left);\r\n\r\n\t\tdstArray.DoneWithPtr\r\n\r\n\t\tEND;\r\n\r\n\tFOR row := rr.bottom TO dstArray.fBlockCount - 1 DO\r\n\t\tBEGIN\r\n\r\n\t\tBlockMove (dstArray.NeedPtr (row - rr.bottom + rr.top,\r\n\t\t\t\t\t\t\t\t\t row - rr.bottom + rr.top,\r\n\t\t\t\t\t\t\t\t\t FALSE),\r\n\t\t\t\t   gBuffer,\r\n\t\t\t\t   dstArray.fLogicalSize);\r\n\r\n\t\tdstArray.DoneWithPtr;\r\n\r\n\t\tBlockMove (gBuffer,\r\n\t\t\t\t   dstArray.NeedPtr (row, row, TRUE),\r\n\t\t\t\t   dstArray.fLogicalSize);\r\n\r\n\t\tdstArray.DoneWithPtr\r\n\r\n\t\tEND;\r\n\r\n\tFOR row := rr.top - 1 DOWNTO 0 DO\r\n\t\tBEGIN\r\n\r\n\t\tBlockMove (dstArray.NeedPtr (row + rr.bottom - rr.top,\r\n\t\t\t\t\t\t\t\t\t row + rr.bottom - rr.top,\r\n\t\t\t\t\t\t\t\t\t FALSE),\r\n\t\t\t\t   gBuffer,\r\n\t\t\t\t   dstArray.fLogicalSize);\r\n\r\n\t\tdstArray.DoneWithPtr;\r\n\r\n\t\tBlockMove (gBuffer,\r\n\t\t\t\t   dstArray.NeedPtr (row, row, TRUE),\r\n\t\t\t\t   dstArray.fLogicalSize);\r\n\r\n\t\tdstArray.DoneWithPtr\r\n\r\n\t\tEND;\r\n\r\n\tdstArray.Flush\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S AToolOptions}\r\n\r\nPROCEDURE AutoRepeatDetect (srcArray: TVMArray; r: Rect; VAR pt: Point);\r\n\r\n\tVAR\r\n\t\tp: Ptr;\r\n\t\tok: BOOLEAN;\r\n\t\trow: INTEGER;\r\n\t\twidth: INTEGER;\r\n\t\theight: INTEGER;\r\n\t\tperiod: INTEGER;\r\n\r\n\tBEGIN\r\n\r\n\twidth  := r.right - r.left;\r\n\theight := r.bottom - r.top;\r\n\r\n\tFOR period := pt.v TO height DO\r\n\t\tIF (period MOD pt.v = 0) OR (period = height) THEN\r\n\t\t\tBEGIN\r\n\r\n\t\t\tok := TRUE;\r\n\r\n\t\t\tFOR row := r.top TO r.bottom - period - 1 DO\r\n\t\t\t\tBEGIN\r\n\r\n\t\t\t\tMoveHands (TRUE);\r\n\r\n\t\t\t\tp := Ptr (ORD4 (srcArray.NeedPtr (row, row, FALSE)) + r.left);\r\n\r\n\t\t\t\tBlockMove (p, gBuffer, width);\r\n\r\n\t\t\t\tsrcArray.DoneWithPtr;\r\n\r\n\t\t\t\tp := Ptr (ORD4 (srcArray.NeedPtr (row + period,\r\n\t\t\t\t\t\t\t\t\t\t\t\t  row + period,\r\n\t\t\t\t\t\t\t\t\t\t\t\t  FALSE)) + r.left);\r\n\r\n\t\t\t\tok := EqualBytes (p, gBuffer, width);\r\n\r\n\t\t\t\tsrcArray.DoneWithPtr;\r\n\r\n\t\t\t\tIF NOT ok THEN LEAVE\r\n\r\n\t\t\t\tEND;\r\n\r\n\t\t\tIF ok THEN\r\n\t\t\t\tBEGIN\r\n\t\t\t\tpt.v := period;\r\n\t\t\t\tLEAVE\r\n\t\t\t\tEND\r\n\r\n\t\t\tEND;\r\n\r\n\tFOR row := r.top TO r.bottom - 1 DO\r\n\t\tIF pt.h &lt;&gt; width THEN\r\n\t\t\tBEGIN\r\n\r\n\t\t\tMoveHands (TRUE);\r\n\r\n\t\t\tp := Ptr (ORD4 (srcArray.NeedPtr (row, row, FALSE)) + r.left);\r\n\r\n\t\t\tFOR period := pt.h TO width DO\r\n\t\t\t\tIF period = width THEN\r\n\t\t\t\t\tpt.h := width\r\n\t\t\t\tELSE IF (period MOD pt.h = 0) &amp;\r\n\t\t\t\t\t\tEqualBytes (p,\r\n\t\t\t\t\t\t\t\t\tPtr (ORD4 (p) + period),\r\n\t\t\t\t\t\t\t\t\twidth - period) THEN\r\n\t\t\t\t\tBEGIN\r\n\t\t\t\t\tpt.h := period;\r\n\t\t\t\t\tLEAVE\r\n\t\t\t\t\tEND;\r\n\r\n\t\t\tsrcArray.DoneWithPtr\r\n\r\n\t\t\tEND;\r\n\r\n\tsrcArray.Flush\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\n{$S AToolOptions}\r\n\r\nPROCEDURE DefinePattern (view: TImageView);\r\n\r\n\tVAR\r\n\t\tr: Rect;\r\n\t\tpt: Point;\r\n\t\tfi: FailInfo;\r\n\t\tband: INTEGER;\r\n\t\twidth: INTEGER;\r\n\t\theight: INTEGER;\r\n\t\tmap: TLookUpTable;\r\n\t\tdoc: TImageDocument;\r\n\r\n\tPROCEDURE CleanUp (error: INTEGER; message: LONGINT);\r\n\r\n\t\tVAR\r\n\t\t\tj: INTEGER;\r\n\r\n\t\tBEGIN\r\n\r\n\t\tgPatternRect := gZeroRect;\r\n\r\n\t\tFOR j := 0 TO 3 DO\r\n\t\t\tBEGIN\r\n\t\t\tFreeObject (gPattern [j]);\r\n\t\t\tgPattern [j] := NIL\r\n\t\t\tEND\r\n\r\n\t\tEND;\r\n\r\n\tBEGIN\r\n\r\n\tCleanUp (0, 0);\r\n\r\n\tCatchFailures (fi, CleanUp);\r\n\r\n\tdoc := TImageDocument (view.fDocument);\r\n\r\n\tr := doc.fSelectionRect;\r\n\r\n\tpt.h := 1;\r\n\tpt.v := 1;\r\n\r\n\tIF view.fChannel = kRGBChannels THEN\r\n\t\tFOR band := 0 TO 2 DO\r\n\t\t\tAutoRepeatDetect (doc.fData [band], r, pt)\r\n\tELSE\r\n\t\tAutoRepeatDetect (doc.fData [view.fChannel], r, pt);\r\n\r\n\tr.right  := r.left + pt.h;\r\n\tr.bottom := r.top  + pt.v;\r\n\r\n\tgPatternRect := r;\r\n\tOffsetRect (gPatternRect, -r.left + kMaxTipSize - 1,\r\n\t\t\t\t\t\t\t  -r.top  + kMaxTipSize - 1);\r\n\r\n\twidth  := gPatternRect.right + gPatternRect.left;\r\n\theight := gPatternRect.bottom + gPatternRect.top;\r\n\r\n\tIF view.fChannel = kRGBChannels THEN\r\n\t\tBEGIN\r\n\r\n\t\tFOR band := 1 TO 3 DO\r\n\t\t\tgPattern [band] := NewVMArray (height, width, 4 - band);\r\n\r\n\t\tFOR band := 1 TO 3 DO\r\n\t\t\tCopyPatternBand (doc.fData [band - 1],\r\n\t\t\t\t\t\t\t gPattern [band],\r\n\t\t\t\t\t\t\t r);\r\n\r\n\t\tgPattern [0] := MakeMonochromeArray (gPattern [1],\r\n\t\t\t\t\t\t\t\t\t\t\t gPattern [2],\r\n\t\t\t\t\t\t\t\t\t\t\t gPattern [3])\r\n\r\n\t\tEND\r\n\r\n\tELSE\r\n\t\tBEGIN\r\n\r\n\t\tgPattern [0] := NewVMArray (height, width, 1);\r\n\r\n\t\tCopyPatternBand (doc.fData [view.fChannel],\r\n\t\t\t\t\t\t gPattern [0],\r\n\t\t\t\t\t\t r);\r\n\r\n\t\tIF doc.fMode = IndexedColorMode THEN\r\n\t\t\tBEGIN\r\n\r\n\t\t\tmap := doc.fIndexedColorTable.R;\r\n\t\t\tgPattern [1] := gPattern [0] . CopyArray (3);\r\n\t\t\tgPattern [1] . MapBytes (map);\r\n\r\n\t\t\tmap := doc.fIndexedColorTable.G;\r\n\t\t\tgPattern [2] := gPattern [0] . CopyArray (2);\r\n\t\t\tgPattern [2] . MapBytes (map);\r\n\r\n\t\t\tmap := doc.fIndexedColorTable.B;\r\n\t\t\tgPattern [3] := gPattern [0] . CopyArray (1);\r\n\t\t\tgPattern [3] . MapBytes (map);\r\n\r\n\t\t\tgPattern [0] . Free;\r\n\t\t\tgPattern [0] := NIL;\r\n\r\n\t\t\tgPattern [0] := MakeMonochromeArray (gPattern [1],\r\n\t\t\t\t\t\t\t\t\t\t\t\t gPattern [2],\r\n\t\t\t\t\t\t\t\t\t\t\t\t gPattern [3])\r\n\r\n\t\t\tEND\r\n\r\n\t\tEND;\r\n\r\n\tdoc.DeSelect (TRUE);\r\n\r\n\tSuccess (fi)\r\n\r\n\tEND;\r\n\r\n{*****************************************************************************}\r\n\r\nEND.\r\n<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u0647\u0646\u06af\u0627\u0645\u06cc \u06a9\u0647 \u0628\u0631\u0627\u062f\u0631\u0627\u0646 Knoll \u0637\u0631\u0627\u062d\u06cc \u0648 \u0646\u0648\u0634\u062a\u0646 \u06cc\u06a9 \u0628\u0631\u0646\u0627\u0645\u0647\u200c\u200c\u0654 \u0648\u06cc\u0631\u0627\u06cc\u0634 \u062a\u0635\u0648\u06cc\u0631 \u0631\u0627 \u062f\u0631 \u0627\u0648\u0627\u062e\u0631 \u062f\u0647\u0647\u0654 \u06f1\u06f9\u06f8\u06f0 \u0622\u063a\u0627\u0632 \u06a9\u0631\u062f\u0646\u062f\u060c \u062d\u062a\u06cc \u062a\u0635\u0648\u0631\u0634 \u0631\u0627 \u0647\u0645 \u0646\u0645\u06cc\u200c\u06a9\u0631\u062f\u0646\u062f \u06a9\u0647 \u0628\u0627 \u0627\u06cc\u0646 \u06a9\u0627\u0631\u060c \u0648\u0627\u0698\u0647\u200c\u0654 \u062c\u062f\u06cc\u062f\u06cc (\u0641\u062a\u0648\u0634\u0627\u067e) \u0631\u0627 \u0628\u0647 \u0648\u0627\u0698\u06af\u0627\u0646 \u06a9\u0627\u0631\u0628\u0631\u062f\u06cc \u0635\u0646\u0627\u06cc\u0639 \u0637\u0631\u0627\u062d\u06cc\u060c \u0645\u064f\u062f\u060c \u0628\u0633\u062a\u0647\u200c\u0628\u0646\u062f\u06cc \u0648 \u062d\u062a\u06cc \u0633\u06cc\u0646\u0645\u0627 \u0627\u0636\u0627\u0641\u0647 \u062e\u0648\u0627\u0647\u0646\u062f \u06a9\u0631\u062f! Thomas Knoll \u062f\u0631 \u0633\u0627\u0644 \u06f1\u06f9\u06f8\u06f7 \u0647\u0646\u06af\u0627\u0645\u06cc \u06a9\u0647 \u062f\u0631 \u062f\u0627\u0646\u0634\u06af\u0627\u0647 \u0645\u06cc\u0634\u06cc\u06af\u0627\u0646 \u062f\u0627\u0646\u0634\u062c\u0648\u06cc&hellip;<\/p>\n","protected":false},"author":1,"featured_media":1250,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[116],"tags":[393,2195],"class_list":["post-7386","post","type-post","status-publish","format-standard","has-post-thumbnail","category-116","tag-393","tag-2195"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.7 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>[\u0628\u0647 \u0631\u0648\u0627\u06cc\u062a \u06a9\u062f] = [\u0633\u0648\u0631\u0633 \u06a9\u062f \u0646\u0633\u062e\u0647 \u0646\u062e\u0633\u062a \u0641\u062a\u0648\u0634\u0627\u067e - \u06f1\u06f9\u06f9\u06f0] - \u0633\u06cc\u062f \u0645\u0647\u062f\u06cc \u0633\u0644\u06cc\u0645\u06cc<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/mehdisalimi.ir\/?p=7386\" \/>\n<meta property=\"og:locale\" content=\"fa_IR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"[\u0628\u0647 \u0631\u0648\u0627\u06cc\u062a \u06a9\u062f] = [\u0633\u0648\u0631\u0633 \u06a9\u062f \u0646\u0633\u062e\u0647 \u0646\u062e\u0633\u062a \u0641\u062a\u0648\u0634\u0627\u067e - \u06f1\u06f9\u06f9\u06f0] - \u0633\u06cc\u062f \u0645\u0647\u062f\u06cc \u0633\u0644\u06cc\u0645\u06cc\" \/>\n<meta property=\"og:description\" content=\"\u0647\u0646\u06af\u0627\u0645\u06cc \u06a9\u0647 \u0628\u0631\u0627\u062f\u0631\u0627\u0646 Knoll \u0637\u0631\u0627\u062d\u06cc \u0648 \u0646\u0648\u0634\u062a\u0646 \u06cc\u06a9 \u0628\u0631\u0646\u0627\u0645\u0647\u200c\u200c\u0654 \u0648\u06cc\u0631\u0627\u06cc\u0634 \u062a\u0635\u0648\u06cc\u0631 \u0631\u0627 \u062f\u0631 \u0627\u0648\u0627\u062e\u0631 \u062f\u0647\u0647\u0654 \u06f1\u06f9\u06f8\u06f0 \u0622\u063a\u0627\u0632 \u06a9\u0631\u062f\u0646\u062f\u060c \u062d\u062a\u06cc \u062a\u0635\u0648\u0631\u0634 \u0631\u0627 \u0647\u0645 \u0646\u0645\u06cc\u200c\u06a9\u0631\u062f\u0646\u062f \u06a9\u0647 \u0628\u0627 \u0627\u06cc\u0646 \u06a9\u0627\u0631\u060c \u0648\u0627\u0698\u0647\u200c\u0654 \u062c\u062f\u06cc\u062f\u06cc (\u0641\u062a\u0648\u0634\u0627\u067e) \u0631\u0627 \u0628\u0647 \u0648\u0627\u0698\u06af\u0627\u0646 \u06a9\u0627\u0631\u0628\u0631\u062f\u06cc \u0635\u0646\u0627\u06cc\u0639 \u0637\u0631\u0627\u062d\u06cc\u060c \u0645\u064f\u062f\u060c \u0628\u0633\u062a\u0647\u200c\u0628\u0646\u062f\u06cc \u0648 \u062d\u062a\u06cc \u0633\u06cc\u0646\u0645\u0627 \u0627\u0636\u0627\u0641\u0647 \u062e\u0648\u0627\u0647\u0646\u062f \u06a9\u0631\u062f! Thomas Knoll \u062f\u0631 \u0633\u0627\u0644 \u06f1\u06f9\u06f8\u06f7 \u0647\u0646\u06af\u0627\u0645\u06cc \u06a9\u0647 \u062f\u0631 \u062f\u0627\u0646\u0634\u06af\u0627\u0647 \u0645\u06cc\u0634\u06cc\u06af\u0627\u0646 \u062f\u0627\u0646\u0634\u062c\u0648\u06cc&hellip;\" \/>\n<meta property=\"og:url\" content=\"https:\/\/mehdisalimi.ir\/?p=7386\" \/>\n<meta property=\"og:site_name\" content=\"\u0633\u06cc\u062f \u0645\u0647\u062f\u06cc \u0633\u0644\u06cc\u0645\u06cc\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/mehdisalimi13\" \/>\n<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/mehdisalimi13\" \/>\n<meta property=\"article:published_time\" content=\"2020-05-05T21:08:45+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/mehdisalimi.ir\/wp-content\/uploads\/code.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"600\" \/>\n\t<meta property=\"og:image:height\" content=\"400\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Mehd!Salimi\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/mehdisalimi13\" \/>\n<meta name=\"twitter:site\" content=\"@mehdisalimi13\" \/>\n<meta name=\"twitter:label1\" content=\"\u0646\u0648\u0634\u062a\u0647\u200c\u0634\u062f\u0647 \u0628\u062f\u0633\u062a\" \/>\n\t<meta name=\"twitter:data1\" content=\"Mehd!Salimi\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u0632\u0645\u0627\u0646 \u062a\u0642\u0631\u06cc\u0628\u06cc \u0628\u0631\u0627\u06cc \u062e\u0648\u0627\u0646\u062f\u0646\" \/>\n\t<meta name=\"twitter:data2\" content=\"52 \u062f\u0642\u06cc\u0642\u0647\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/mehdisalimi.ir\\\/?p=7386#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/mehdisalimi.ir\\\/?p=7386\"},\"author\":{\"name\":\"Mehd!Salimi\",\"@id\":\"https:\\\/\\\/mehdisalimi.ir\\\/#\\\/schema\\\/person\\\/aa4ebf7fb5115362f325b292af001e65\"},\"headline\":\"[\u0628\u0647 \u0631\u0648\u0627\u06cc\u062a \u06a9\u062f] = [\u0633\u0648\u0631\u0633 \u06a9\u062f \u0646\u0633\u062e\u0647 \u0646\u062e\u0633\u062a \u0641\u062a\u0648\u0634\u0627\u067e &#8211; \u06f1\u06f9\u06f9\u06f0]\",\"datePublished\":\"2020-05-05T21:08:45+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/mehdisalimi.ir\\\/?p=7386\"},\"wordCount\":27,\"publisher\":{\"@id\":\"https:\\\/\\\/mehdisalimi.ir\\\/#\\\/schema\\\/person\\\/aa4ebf7fb5115362f325b292af001e65\"},\"image\":{\"@id\":\"https:\\\/\\\/mehdisalimi.ir\\\/?p=7386#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/mehdisalimi.ir\\\/wp-content\\\/uploads\\\/code.jpg\",\"keywords\":[\"\u0628\u0647 \u0631\u0648\u0627\u06cc\u062a \u06a9\u062f\",\"\u0633\u0648\u0631\u0633 \u06a9\u062f \u0641\u062a\u0648\u0634\u0627\u067e\"],\"articleSection\":[\"\u0628\u0647 \u0631\u0648\u0627\u06cc\u062a \u06a9\u062f\"],\"inLanguage\":\"fa-IR\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/mehdisalimi.ir\\\/?p=7386\",\"url\":\"https:\\\/\\\/mehdisalimi.ir\\\/?p=7386\",\"name\":\"[\u0628\u0647 \u0631\u0648\u0627\u06cc\u062a \u06a9\u062f] = [\u0633\u0648\u0631\u0633 \u06a9\u062f \u0646\u0633\u062e\u0647 \u0646\u062e\u0633\u062a \u0641\u062a\u0648\u0634\u0627\u067e - \u06f1\u06f9\u06f9\u06f0] - \u0633\u06cc\u062f \u0645\u0647\u062f\u06cc \u0633\u0644\u06cc\u0645\u06cc\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/mehdisalimi.ir\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/mehdisalimi.ir\\\/?p=7386#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/mehdisalimi.ir\\\/?p=7386#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/mehdisalimi.ir\\\/wp-content\\\/uploads\\\/code.jpg\",\"datePublished\":\"2020-05-05T21:08:45+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/mehdisalimi.ir\\\/?p=7386#breadcrumb\"},\"inLanguage\":\"fa-IR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/mehdisalimi.ir\\\/?p=7386\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"fa-IR\",\"@id\":\"https:\\\/\\\/mehdisalimi.ir\\\/?p=7386#primaryimage\",\"url\":\"https:\\\/\\\/mehdisalimi.ir\\\/wp-content\\\/uploads\\\/code.jpg\",\"contentUrl\":\"https:\\\/\\\/mehdisalimi.ir\\\/wp-content\\\/uploads\\\/code.jpg\",\"width\":600,\"height\":400},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/mehdisalimi.ir\\\/?p=7386#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u062e\u0627\u0646\u0647\",\"item\":\"https:\\\/\\\/mehdisalimi.ir\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"[\u0628\u0647 \u0631\u0648\u0627\u06cc\u062a \u06a9\u062f] = [\u0633\u0648\u0631\u0633 \u06a9\u062f \u0646\u0633\u062e\u0647 \u0646\u062e\u0633\u062a \u0641\u062a\u0648\u0634\u0627\u067e &#8211; \u06f1\u06f9\u06f9\u06f0]\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/mehdisalimi.ir\\\/#website\",\"url\":\"https:\\\/\\\/mehdisalimi.ir\\\/\",\"name\":\"\u0633\u06cc\u062f \u0645\u0647\u062f\u06cc \u0633\u0644\u06cc\u0645\u06cc\",\"description\":\"[\u06cc\u0627\u062f\u062f\u0627\u0634\u062a \u0647\u0627 \u0648 \u0647\u0631 \u0627\u0632 \u06af\u0627\u0647\u06cc \u0686\u0646\u062f \u062e\u0637 \u06a9\u062f]\",\"publisher\":{\"@id\":\"https:\\\/\\\/mehdisalimi.ir\\\/#\\\/schema\\\/person\\\/aa4ebf7fb5115362f325b292af001e65\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/mehdisalimi.ir\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"fa-IR\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/mehdisalimi.ir\\\/#\\\/schema\\\/person\\\/aa4ebf7fb5115362f325b292af001e65\",\"name\":\"Mehd!Salimi\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"fa-IR\",\"@id\":\"https:\\\/\\\/mehdisalimi.ir\\\/wp-content\\\/uploads\\\/2020\\\/04\\\/llog2.png\",\"url\":\"https:\\\/\\\/mehdisalimi.ir\\\/wp-content\\\/uploads\\\/2020\\\/04\\\/llog2.png\",\"contentUrl\":\"https:\\\/\\\/mehdisalimi.ir\\\/wp-content\\\/uploads\\\/2020\\\/04\\\/llog2.png\",\"width\":450,\"height\":180,\"caption\":\"Mehd!Salimi\"},\"logo\":{\"@id\":\"https:\\\/\\\/mehdisalimi.ir\\\/wp-content\\\/uploads\\\/2020\\\/04\\\/llog2.png\"},\"sameAs\":[\"http:\\\/\\\/www.mehdisalimi.ir\",\"https:\\\/\\\/www.facebook.com\\\/mehdisalimi13\",\"https:\\\/\\\/ir.linkedin.com\\\/in\\\/mehdisalimi13\",\"https:\\\/\\\/x.com\\\/https:\\\/\\\/twitter.com\\\/mehdisalimi13\"],\"url\":\"https:\\\/\\\/mehdisalimi.ir\\\/?author=1\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"[\u0628\u0647 \u0631\u0648\u0627\u06cc\u062a \u06a9\u062f] = [\u0633\u0648\u0631\u0633 \u06a9\u062f \u0646\u0633\u062e\u0647 \u0646\u062e\u0633\u062a \u0641\u062a\u0648\u0634\u0627\u067e - \u06f1\u06f9\u06f9\u06f0] - \u0633\u06cc\u062f \u0645\u0647\u062f\u06cc \u0633\u0644\u06cc\u0645\u06cc","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/mehdisalimi.ir\/?p=7386","og_locale":"fa_IR","og_type":"article","og_title":"[\u0628\u0647 \u0631\u0648\u0627\u06cc\u062a \u06a9\u062f] = [\u0633\u0648\u0631\u0633 \u06a9\u062f \u0646\u0633\u062e\u0647 \u0646\u062e\u0633\u062a \u0641\u062a\u0648\u0634\u0627\u067e - \u06f1\u06f9\u06f9\u06f0] - \u0633\u06cc\u062f \u0645\u0647\u062f\u06cc \u0633\u0644\u06cc\u0645\u06cc","og_description":"\u0647\u0646\u06af\u0627\u0645\u06cc \u06a9\u0647 \u0628\u0631\u0627\u062f\u0631\u0627\u0646 Knoll \u0637\u0631\u0627\u062d\u06cc \u0648 \u0646\u0648\u0634\u062a\u0646 \u06cc\u06a9 \u0628\u0631\u0646\u0627\u0645\u0647\u200c\u200c\u0654 \u0648\u06cc\u0631\u0627\u06cc\u0634 \u062a\u0635\u0648\u06cc\u0631 \u0631\u0627 \u062f\u0631 \u0627\u0648\u0627\u062e\u0631 \u062f\u0647\u0647\u0654 \u06f1\u06f9\u06f8\u06f0 \u0622\u063a\u0627\u0632 \u06a9\u0631\u062f\u0646\u062f\u060c \u062d\u062a\u06cc \u062a\u0635\u0648\u0631\u0634 \u0631\u0627 \u0647\u0645 \u0646\u0645\u06cc\u200c\u06a9\u0631\u062f\u0646\u062f \u06a9\u0647 \u0628\u0627 \u0627\u06cc\u0646 \u06a9\u0627\u0631\u060c \u0648\u0627\u0698\u0647\u200c\u0654 \u062c\u062f\u06cc\u062f\u06cc (\u0641\u062a\u0648\u0634\u0627\u067e) \u0631\u0627 \u0628\u0647 \u0648\u0627\u0698\u06af\u0627\u0646 \u06a9\u0627\u0631\u0628\u0631\u062f\u06cc \u0635\u0646\u0627\u06cc\u0639 \u0637\u0631\u0627\u062d\u06cc\u060c \u0645\u064f\u062f\u060c \u0628\u0633\u062a\u0647\u200c\u0628\u0646\u062f\u06cc \u0648 \u062d\u062a\u06cc \u0633\u06cc\u0646\u0645\u0627 \u0627\u0636\u0627\u0641\u0647 \u062e\u0648\u0627\u0647\u0646\u062f \u06a9\u0631\u062f! Thomas Knoll \u062f\u0631 \u0633\u0627\u0644 \u06f1\u06f9\u06f8\u06f7 \u0647\u0646\u06af\u0627\u0645\u06cc \u06a9\u0647 \u062f\u0631 \u062f\u0627\u0646\u0634\u06af\u0627\u0647 \u0645\u06cc\u0634\u06cc\u06af\u0627\u0646 \u062f\u0627\u0646\u0634\u062c\u0648\u06cc&hellip;","og_url":"https:\/\/mehdisalimi.ir\/?p=7386","og_site_name":"\u0633\u06cc\u062f \u0645\u0647\u062f\u06cc \u0633\u0644\u06cc\u0645\u06cc","article_publisher":"https:\/\/www.facebook.com\/mehdisalimi13","article_author":"https:\/\/www.facebook.com\/mehdisalimi13","article_published_time":"2020-05-05T21:08:45+00:00","og_image":[{"width":600,"height":400,"url":"https:\/\/mehdisalimi.ir\/wp-content\/uploads\/code.jpg","type":"image\/jpeg"}],"author":"Mehd!Salimi","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/mehdisalimi13","twitter_site":"@mehdisalimi13","twitter_misc":{"\u0646\u0648\u0634\u062a\u0647\u200c\u0634\u062f\u0647 \u0628\u062f\u0633\u062a":"Mehd!Salimi","\u0632\u0645\u0627\u0646 \u062a\u0642\u0631\u06cc\u0628\u06cc \u0628\u0631\u0627\u06cc \u062e\u0648\u0627\u0646\u062f\u0646":"52 \u062f\u0642\u06cc\u0642\u0647"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/mehdisalimi.ir\/?p=7386#article","isPartOf":{"@id":"https:\/\/mehdisalimi.ir\/?p=7386"},"author":{"name":"Mehd!Salimi","@id":"https:\/\/mehdisalimi.ir\/#\/schema\/person\/aa4ebf7fb5115362f325b292af001e65"},"headline":"[\u0628\u0647 \u0631\u0648\u0627\u06cc\u062a \u06a9\u062f] = [\u0633\u0648\u0631\u0633 \u06a9\u062f \u0646\u0633\u062e\u0647 \u0646\u062e\u0633\u062a \u0641\u062a\u0648\u0634\u0627\u067e &#8211; \u06f1\u06f9\u06f9\u06f0]","datePublished":"2020-05-05T21:08:45+00:00","mainEntityOfPage":{"@id":"https:\/\/mehdisalimi.ir\/?p=7386"},"wordCount":27,"publisher":{"@id":"https:\/\/mehdisalimi.ir\/#\/schema\/person\/aa4ebf7fb5115362f325b292af001e65"},"image":{"@id":"https:\/\/mehdisalimi.ir\/?p=7386#primaryimage"},"thumbnailUrl":"https:\/\/mehdisalimi.ir\/wp-content\/uploads\/code.jpg","keywords":["\u0628\u0647 \u0631\u0648\u0627\u06cc\u062a \u06a9\u062f","\u0633\u0648\u0631\u0633 \u06a9\u062f \u0641\u062a\u0648\u0634\u0627\u067e"],"articleSection":["\u0628\u0647 \u0631\u0648\u0627\u06cc\u062a \u06a9\u062f"],"inLanguage":"fa-IR"},{"@type":"WebPage","@id":"https:\/\/mehdisalimi.ir\/?p=7386","url":"https:\/\/mehdisalimi.ir\/?p=7386","name":"[\u0628\u0647 \u0631\u0648\u0627\u06cc\u062a \u06a9\u062f] = [\u0633\u0648\u0631\u0633 \u06a9\u062f \u0646\u0633\u062e\u0647 \u0646\u062e\u0633\u062a \u0641\u062a\u0648\u0634\u0627\u067e - \u06f1\u06f9\u06f9\u06f0] - \u0633\u06cc\u062f \u0645\u0647\u062f\u06cc \u0633\u0644\u06cc\u0645\u06cc","isPartOf":{"@id":"https:\/\/mehdisalimi.ir\/#website"},"primaryImageOfPage":{"@id":"https:\/\/mehdisalimi.ir\/?p=7386#primaryimage"},"image":{"@id":"https:\/\/mehdisalimi.ir\/?p=7386#primaryimage"},"thumbnailUrl":"https:\/\/mehdisalimi.ir\/wp-content\/uploads\/code.jpg","datePublished":"2020-05-05T21:08:45+00:00","breadcrumb":{"@id":"https:\/\/mehdisalimi.ir\/?p=7386#breadcrumb"},"inLanguage":"fa-IR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/mehdisalimi.ir\/?p=7386"]}]},{"@type":"ImageObject","inLanguage":"fa-IR","@id":"https:\/\/mehdisalimi.ir\/?p=7386#primaryimage","url":"https:\/\/mehdisalimi.ir\/wp-content\/uploads\/code.jpg","contentUrl":"https:\/\/mehdisalimi.ir\/wp-content\/uploads\/code.jpg","width":600,"height":400},{"@type":"BreadcrumbList","@id":"https:\/\/mehdisalimi.ir\/?p=7386#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u062e\u0627\u0646\u0647","item":"https:\/\/mehdisalimi.ir\/"},{"@type":"ListItem","position":2,"name":"[\u0628\u0647 \u0631\u0648\u0627\u06cc\u062a \u06a9\u062f] = [\u0633\u0648\u0631\u0633 \u06a9\u062f \u0646\u0633\u062e\u0647 \u0646\u062e\u0633\u062a \u0641\u062a\u0648\u0634\u0627\u067e &#8211; \u06f1\u06f9\u06f9\u06f0]"}]},{"@type":"WebSite","@id":"https:\/\/mehdisalimi.ir\/#website","url":"https:\/\/mehdisalimi.ir\/","name":"\u0633\u06cc\u062f \u0645\u0647\u062f\u06cc \u0633\u0644\u06cc\u0645\u06cc","description":"[\u06cc\u0627\u062f\u062f\u0627\u0634\u062a \u0647\u0627 \u0648 \u0647\u0631 \u0627\u0632 \u06af\u0627\u0647\u06cc \u0686\u0646\u062f \u062e\u0637 \u06a9\u062f]","publisher":{"@id":"https:\/\/mehdisalimi.ir\/#\/schema\/person\/aa4ebf7fb5115362f325b292af001e65"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/mehdisalimi.ir\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"fa-IR"},{"@type":["Person","Organization"],"@id":"https:\/\/mehdisalimi.ir\/#\/schema\/person\/aa4ebf7fb5115362f325b292af001e65","name":"Mehd!Salimi","image":{"@type":"ImageObject","inLanguage":"fa-IR","@id":"https:\/\/mehdisalimi.ir\/wp-content\/uploads\/2020\/04\/llog2.png","url":"https:\/\/mehdisalimi.ir\/wp-content\/uploads\/2020\/04\/llog2.png","contentUrl":"https:\/\/mehdisalimi.ir\/wp-content\/uploads\/2020\/04\/llog2.png","width":450,"height":180,"caption":"Mehd!Salimi"},"logo":{"@id":"https:\/\/mehdisalimi.ir\/wp-content\/uploads\/2020\/04\/llog2.png"},"sameAs":["http:\/\/www.mehdisalimi.ir","https:\/\/www.facebook.com\/mehdisalimi13","https:\/\/ir.linkedin.com\/in\/mehdisalimi13","https:\/\/x.com\/https:\/\/twitter.com\/mehdisalimi13"],"url":"https:\/\/mehdisalimi.ir\/?author=1"}]}},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/mehdisalimi.ir\/index.php?rest_route=\/wp\/v2\/posts\/7386","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mehdisalimi.ir\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mehdisalimi.ir\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mehdisalimi.ir\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mehdisalimi.ir\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=7386"}],"version-history":[{"count":2,"href":"https:\/\/mehdisalimi.ir\/index.php?rest_route=\/wp\/v2\/posts\/7386\/revisions"}],"predecessor-version":[{"id":7388,"href":"https:\/\/mehdisalimi.ir\/index.php?rest_route=\/wp\/v2\/posts\/7386\/revisions\/7388"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/mehdisalimi.ir\/index.php?rest_route=\/wp\/v2\/media\/1250"}],"wp:attachment":[{"href":"https:\/\/mehdisalimi.ir\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=7386"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mehdisalimi.ir\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=7386"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mehdisalimi.ir\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=7386"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}