=head
 NAME: TL_PUB_update_sm_defined_opening
 DESCRIPTION: Update soldermask opening which covered by copper or heavy line
 PARAMETER:
	[
        {
			name : 'step_filter',
			type : 'LineEdit',
			title : 'step过滤',
			pack : {row:0,column:1},
			property:{tool_tip:'选择step时候的过滤器'},
		},
		{
			name : 'drill_layer',
			type : 'LineEdit',
			title : '外层机械钻孔层',
			pack : {row:0,column:1},
			property:{tool_tip:''},
		},
		{
			name : 'smd',
			title : '处理SMD盘',
			type : 'RadioBox',
			property : {
				size_policy:'Expanding,Fixed',
				item_list:[
					{name:'Yes',text:'Yes'},
					{name:'No',text:'No'},
				],
				tool_tip:'是否处理SMD盘'
			},
			pack : {row:1,column:1},
            value : 'Yes'
		},
		{
			name : 'bga',
			title : '处理BGA盘',
			type : 'RadioBox',
			property : {
				size_policy:'Expanding,Fixed',
				item_list:[
					{name:'Yes',text:'Yes'},
					{name:'No',text:'No'},
				],
				tool_tip:'是否处理BGA盘'
			},
			pack : {row:1,column:1},
            value : 'Yes'
		},
		{
			name : 'pth',
			title : '处理非Via孔的pth孔盘',
			type : 'RadioBox',
			property : {
				size_policy:'Expanding,Fixed',
				item_list:[
					{name:'Yes',text:'Yes'},
					{name:'No',text:'No'},
				],
				tool_tip:'是否处理PTH所对应的盘'
			},
			pack : {row:1,column:1},
            value : 'No'
		},
		{
			name : 'via',
			title : '处理Via孔盘',
			type : 'RadioBox',
			property : {
				size_policy:'Expanding,Fixed',
				item_list:[
					{name:'Yes',text:'Yes'},
					{name:'No',text:'No'},
				],
				tool_tip:'是否处理Via孔所对应的盘'
			},
			pack : {row:1,column:1},
            value : 'No'
		},
		{
			name : 'pad',
			title : '处理其它盘',
			type : 'RadioBox',
			property : {
				size_policy:'Expanding,Fixed',
				item_list:[
					{name:'Yes',text:'Yes'},
					{name:'No',text:'No'},
				],
				tool_tip:'是否处理除SMD,BGA,和PTH孔对应盘以外的所有pad'
			},
			pack : {row:1,column:1},
            value : 'No'
		},
		{
			name : 'include_pad',
			title : '附近无开窗pad当大铜面',
			type : 'RadioBox',
			property : {
				size_policy:'Expanding,Fixed',
				item_list:[
					{name:'Yes',text:'Yes'},
					{name:'No',text:'No'},
				],
				tool_tip:'附近无开窗pad当大铜面'
			},
			pack : {row:1,column:1},
            value : 'No'
		},
		{
			name : 'ignore_bgasmd',
			title : '允许smdbga上的盘制作',
			type : 'RadioBox',
			property : {
				size_policy:'Expanding,Fixed',
				item_list:[
					{name:'Yes',text:'Yes'},
					{name:'No',text:'No'},
				],
				tool_tip:'除SMD,BGA外的盘在做完bga和smd后任运行制作'
			},
			pack : {row:1,column:1},
            value : 'No'
		},
		{
			name : 'make_sm_less_pad',
			title : '自动优化防焊ON PAD',
			type : 'RadioBox',
			property : {
				size_policy:'Expanding,Fixed',
				item_list:[
					{name:'Yes',text:'Yes'},
					{name:'No',text:'No'},
				],
				tool_tip:'默认参数为铜面上单边开窗(mil)大小'
			},
			pack : {row:1,column:1},
            value : 'No'
		},
		{
			name : 'delete_samll_area',
			title : '允许删除小面积开窗',
			type : 'RadioBox',
			property : {
				size_policy:'Expanding,Fixed',
				item_list:[
					{name:'Yes',text:'Yes'},
					{name:'No',text:'No'},
				],
				tool_tip:'允许删除小面积开窗'
			},
			pack : {row:1,column:1},
            value : 'No'
		},
		{
			name : 'small_area_open',
			type : 'LineEdit',
			title : '认为是小面积开窗的面积',
			pack : {row:0,column:1},
            units:'mil',
			property:{tool_tip:'认为是小面积开窗的面积大小,默认0.01'},
            value : 10
		},
		{
			name : 'smd_line',
			type : 'LineEdit',
			title : 'SMD认为是铜面的最小线',
			pack : {row:0,column:1},
            units:'mil',
			property:{tool_tip:'SMD认为是铜面的最小线'},
            value : 10
		},
		{
			name : 'bga_line',
			type : 'LineEdit',
			title : 'BGA认为是铜面的最小线',
			pack : {row:0,column:1},
            units:'mil',
			property:{tool_tip:'BGA认为是铜面的最小线'},
            value : 5
		},
		{
			name : 'coverage',
			type : 'LineEdit',
			title : '最小Coverage(去除Coverage Tol)',
			pack : {row:0,column:1},
            units:'mil',
			property:{tool_tip:'最小Coverage'},
            value : 2
		},
		{
			name : 'coverage_tol',
			type : 'LineEdit',
			title : 'Coverage Tol',
			pack : {row:0,column:1},
            units:'mil',
			property:{tool_tip:'主要用于铜面比线路pad稍微大一点时,忽略宽度的值,会纳入最小Coverage计算'},
            value : 2
		},
		{
			name : 'bga_copperopen',
			type : 'LineEdit',
			title : 'BGA铜面上单边开窗',
			pack : {row:0,column:1},
            units:'mil',
			property:{tool_tip:'BGA铜面上单边开窗'},
            value : 0.5
		},
		{
			name : 'spec_bga_copperopen',
			type : 'LineEdit',
			title : '特殊BGA铜面上单边开窗',
			pack : {row:0,column:1},
            units:'mil',
			property:{tool_tip:'特殊BGA铜面上单边开窗'},
            value : 0.5
		},
		{
			name : 'smd_copperopen',
			type : 'LineEdit',
			title : 'SMD铜面上单边开窗',
			pack : {row:0,column:1},
            units:'mil',
			property:{tool_tip:'SMD铜面上单边开窗'},
            value : 0.5
		},
        {
			name : 'pth_copperopen',
			type : 'LineEdit',
			title : 'PTH孔盘铜面上单边开窗',
			pack : {row:0,column:1},
            units:'mil',
			property:{tool_tip:'PTH孔盘铜面上单边开窗'},
            value : 0.5
		},
        {
			name : 'via_copperopen',
			type : 'LineEdit',
			title : 'VIA孔盘铜面上单边开窗',
			pack : {row:0,column:1},
            units:'mil',
			property:{tool_tip:'VIA孔盘铜面上单边开窗'},
            value : 0.5
		},
        {
			name : 'pad_copperopen',
			type : 'LineEdit',
			title : '其他PAD铜面上单边开窗',
			pack : {row:0,column:1},
            units:'mil',
			property:{tool_tip:'其他PAD铜面上单边开窗'},
            value : 0.5
		},
        {
			name : 'opt_open',
			type : 'LineEdit',
			title : '正常最优单边开窗',
			pack : {row:0,column:1},
            units:'mil',
			property:{tool_tip:'正常最优单边开窗'},
            value : 1.5
		},
		{
			name : 'update_max_opening',
			type : 'LineEdit',
			title : '允许优化的单边最大开窗',
			pack : {row:0,column:1},
            units:'mil',
			property:{tool_tip:'pad单边放大这个值后,开窗在里面的才优化'},
            value : 3
		},
		{
			name : 'keep_gasket',
			type : 'RadioBox',
			title : '是否保证Gasket',
			property : {
                tool_tip:'是否保证开窗下面的垫圈',
				size_policy:'Expanding,Fixed',
				item_list:[
					{name:'Yes',text:'Yes'},
					{name:'No',text:'No'}
				]
			},
			pack : {row:0,column:2},
			value:'No'
		},
		{
			name : 'gasket_size',
			type : 'LineEdit',
			title : '开窗gasket最小',
			pack : {row:0,column:1},
            units:'mil',
			property:{tool_tip:'为了保证完全落于铜面的开窗大小,对于靠在边上的下面加垫圈'},
            value:1.5
		},
		{
			name : 'bga_attr',
			type : 'LineEdit',
			title : '定义为BGA Pad的属性名字',
			pack : {row:0,column:1},
            units:'mil',
			property:{tool_tip:'定义BGA的属性名字'},
            value:'.bga'
		},
		{
			name : 'smd_attr',
			type : 'LineEdit',
			title : '定义为SMD Pad的属性名字',
			pack : {row:0,column:1},
            units:'mil',
			property:{tool_tip:'定义SMD的属性名字'},
            value:'.smd'
		},
		{
			name : 'ignore_attr',
			type : 'LineEdit',
			title : 'SM忽略处理开窗的属性名字',
			pack : {row:0,column:1},
            units:'mil',
			property:{tool_tip:'定义需要被忽略处理的开窗所加属性名字'},
            value:'.ignore_action'
		},
		{
			name : 'include_teardrop',
			type : 'RadioBox',
			title : '大铜面包含.tear_drop',
			property : {
                tool_tip:'碰到大铜面或者粗线的.tear_drop是否也当成大铜面处理',
				size_policy:'Expanding,Fixed',
				item_list:[
					{name:'Yes',text:'Yes'},
					{name:'No',text:'No'},
                    {name:'Manual',text:'Manual'},
				]
			},
			pack : {row:0,column:2},
			value:'No'
		},
		{
			name : 'laser_pad_attr',
			type : 'LineEdit',
			title : '镭射Pad属性',
			pack : {row:0,column:1},
            units:'mil',
			property:{tool_tip:'定义Laser Pad的属性名字'},
            value:''
		},
		{
			name : 'ignore_attr_comp',
			type : 'RadioBox',
			title : '补偿有属性的忽略开窗',
			property : {
                tool_tip:'对定义属性的开窗,是否进行铜面补偿',
				size_policy:'Expanding,Fixed',
				item_list:[
					{name:'Yes',text:'Yes'},
					{name:'No',text:'No'}
				]
			},
			pack : {row:0,column:2},
			value:'No'
		},
        {
			name : 'specifical_opening_suffix',
			type : 'LineEdit',
			title : '特殊情况报警层后缀',
			pack : {row:0,column:1},
            units:'mil',
			property:{tool_tip:'定义特殊的开窗不能处理,报警层后缀名'},
            value:''
		},
        {
			name : 'backup_suffix',
			type : 'LineEdit',
			title : '备份层后缀',
			pack : {row:0,column:1},
            units:'mil',
			property:{tool_tip:'定义备份层后缀名'},
            value:'._tl+++'
		},
        {
			name : 'is_select_lyr',
			title : '选择层别',
			type : 'RadioBox',
			property : {
				size_policy:'Expanding,Fixed',
				item_list:[
					{name:'Yes',text:'Yes'},
					{name:'No',text:'No'},
				],
				tool_tip:'未设定,默认为yes'
			},
			pack : {row:1,column:1},
            value : 'Yes'
		},
	]
	
 VERSION_HISTORY:
	V1.00 2011-03-28 Jacket Wu
	    Release first version according to request
    V1.10 2011-06-01 Jacket Wu
		增加了补偿值对忽略的属性,并有参数可以定义
	V1.20 2011-06-03 Jacket Wu
		修正bug,对于特殊属性补偿,系统运行根据需要做的情况有好几次,目前改为一次
    V1.30 2012-01-10 Jacket Wu
		最优窗口支持不同pad size有不同的值,可以定义为如下的一个结构或者一个值
        [{min=>0,max=>10,cmp=>2.5},{min=>10,max=>10000,cmp=>2},{type=>'others',cmp=>2}]
    V1.40 2012-01-17 Jacket Wu
		调整料号选择,可以支持几个料号名字优先排列
    V1.50 2012-01-19 Jacket Wu
		添加备份层后缀名参数
    V1.51 2012-02-02 Jacket Wu
		更改开窗大小的时候pad从大到小改
    V1.52 2012-02-16 Jacket Wu
		对于需要shave的地方,如果在sm层碰到surface就去掉
    V1.60 2013-07-09 Jacket Wu
		分开不同类型pad可以设定不同的铜面开窗大小
	V1.70 2015-04-16 Jacket Wu
		1. 修正整个负数据覆盖pad及部分pad 不应该处理也处理的情况
		2. 增加允许对单边开窗用负的数据,就是开窗比pad小
	V1.71 2015-04-21 Jacket Wu
		1.分开标准pth孔与via孔可以设定不同的铜面开窗大小
        2.优化执行效率
	V1.72 2015-04-24 Sting Chen
		1.优化转换铜面参数
    V1.73 2016-11-21 Cody Yu
		1.脚本参数转换为c++格式
    V1.74 2016-12-09 Cody Yu
		1.铜面上的开窗,在参数确认界面上自动缩小补偿值
    V1.75 2018-05-02 Shyer Wang 
		1.去除2018-3-23更改逻辑
        2.修复铜面重复pad不做优化的问题
    V1.76 2018-05-11 Shyer Wang 
		1.更改界面默认参数
        2.取消pad碰到钻孔不做sm_defined的逻辑
		3.增加附近无开窗pad当大铜面参数设置
		4.增加允许smdbga上的盘再次制作sm_defined的参数设置
    V1.77 2018-05-15 Shyer Wang 
		1.去除普通pad碰到pth孔
    V1.78 2018-05-16 Shyer Wang 
		1.开窗层过滤掉负性物件制作
        2.via负性和sm_defined合并
    V1.79 2018-05-17 Shyer Wang 
		1.增加脚本参数控制是否清除小面积开窗
        2.增加脚本参数设置清除小面积开窗的面积
    V1.80 2018-05-19 Shyer Wang 
		1.优化尖角
        2.优化负属性物件制作逻辑
    V1.81 2018-05-29 Shyer Wang 
		1.on pad制作增加脚本参数控制
        2.修复负片层确实问题
    V1.82 2018-06-04 Shyer Wang 
		1.优化负片逻辑
        2.大铜面碰到的pad选择逻辑变更
    V1.83 2018-06-04 Shyer Wang 
		1.优化增加泪滴逻辑
        2.增加特殊bga参数‘tl_spec_bga’
    V1.84 2018-08-07 Shyer Wang 
		1.增加coverage 公差,用于支持线与smd等等大情况的
    V1.85 2018-08-15 Shyer Wang 
		1.前台界面增加是否忽略泪滴的脚本参数
    V1.86 2018-09-25 Alan
		1.修复via盘参数选择no,还处理的bug  
                
 HELP:
	<html><body bgcolor="#DDECFE">
		<font size="3" color="#003DB2"><p>功能简介</p><br></font>
		  <p>分开处理在铜面上的Pad开窗和正常没有铜面开窗</p><br>
		  <br>
		<font size="3" color="#003DB2"><p>参数配置</p><br></font>
		<font color="#008000"><p> ● 料号名</p><br></font>
		  <p> 设置genesis中料号的名字,${JOB}表示跟TopCAM中的料号名字一样,TL_genesis_work_jobname表示用这个料号属性定义的名字</p><br>
		<font color="#008000"><p> ● step过滤</p><br></font>
		  <p> 选择step时候的过滤器</p><br>
		<font color="#008000"><p> ● 外层机械钻孔层</p><br></font>
		  <p> 定义外层机械钻孔层得固定名字</p><br>
		<font color="#008000"><p> ● 处理SMD盘</p><br></font>
		  <p> 定义缺省的是否处理SMD pad</p><br>
		<font color="#008000"><p> ● 处理BGA盘</p><br></font>
		  <p> 定义缺省的是否处理BGA pad</p><br>
		<font color="#008000"><p> ● 处理pth 孔盘</p><br></font>
		  <p> 定义缺省的是否处理非via孔的PTH孔所对应的盘</p><br>
		<font color="#008000"><p> ● 处理via 孔盘</p><br></font>
		  <p> 定义缺省的是否处理via孔所对应的盘</p><br>
		<font color="#008000"><p> ● 处理其它盘</p><br></font>
		  <p> 定义缺省的是否处理除SMD,BGA,PTH和Via孔对应盘以外的所有pad</p><br>
		<font color="#008000"><p> ● SMD认为是铜面的最小线</p><br></font>
		  <p> 对于非BGA盘对应的线,需要当作铜面处理的最小线宽。也就是大于等于这个线宽的线并且跟盘相连,将当铜面处理</p><br>
		<font color="#008000"><p> ● BGA认为是铜面的最小线</p><br></font>
		  <p> 对于BGA盘对应的线,需要当作铜面处理的最小线宽。也就是大于等于这个线宽的线并且是跟BGA相连,将当铜面处理</p><br>
		<font color="#008000"><p> ● 最小Coverage</p><br></font>
		  <p> 定义缺省开窗到线或需要用绿油盖起来的元素的最小安全距离</p><br>
		<font color="#008000"><p> ● 铜面上单边开窗</p><br></font>
		  <p> pad落于大铜面上的开窗的大小要求,指的是单面的</p><br>
		<font color="#008000"><p> ● 正常最优单边开窗</p><br></font>
		  <p> 没有落于大铜面的最优开窗大小,指的是单边的</p><br>
		<font color="#008000"><p> ● 允许优化的单边最大开窗</p><br></font>
		  <p> 定义允许进行优化操作的最大单边开窗,如果开窗超过这个值,将不进行优化</p><br>
		<font color="#008000"><p> ● 是否保证Gasket</p><br></font>
		  <p> 定义对开窗正好在大铜面边上,并且都落于大铜面上,是否要在外层加个垫圈,以防治开窗制作公差引起铜面变小</p><br>
		<font color="#008000"><p> ● 开窗gasket最小</p><br></font>
		  <p> 在需要保证gastet的情况下,铜面必须比开窗单边大的尺寸要求</p><br>
		<font color="#008000"><p> ● 定义为BGA Pad的属性名字</p><br></font>
		  <p> BGA pad所加的属性名字</p><br>
		<font color="#008000"><p> ● 定义为SMD Pad的属性名字</p><br></font>
		  <p> SMD pad所加的属性名字</p><br>
		<font color="#008000"><p> ● SM忽略处理开窗的属性名字</p><br></font>
		  <p> 定义需要被忽略处理的属性名字,这个属性名字是加在 solder mask层上的</p><br>
		<font color="#008000"><p> ● 大铜面包含.tear_drop</p><br></font>
		  <p> 定义碰到大铜面或者粗线的.tear_drop是否也当成大铜面处理</p><br>
		<font color="#008000"><p> ● 镭射Pad属性</p><br></font>
		  <p> 定义laser pad属性名字,如果定义了laser pad,系统将把laser pad过滤掉来处理</p><br>
		<font color="#008000"><p> ● 补偿有属性的忽略开窗</p><br></font>
		  <p> 对于定义需要被忽略处理的开窗,是否需要做大铜面补偿值</p><br>
		<font size="3" color="#003DB2"><p>注意事项</p><br></font>
		  <p> ● 在solder mask层上面是surface的将不被优化</p><br>
		  <p> ● 如果一个开窗下面对应有超过并等于2个盘得情况也将不做处理</p><br>
		  <p> ● 对于开窗形状和pad形状不是相同的情况下也将过滤不处理</p><br>
		  <br>
	</body></html>
  
=cut
use strict;
#my ($JOB,$GEN,$GUI,$DB,$JOB_ID,$PAR);

#####使用时间控制
#my $year = (localtime())[5] + 1900;
#my $mon = (localtime())[4];
#if ( $year > 2012 or ($year == 2012 and $mon > 12) ) {
#	$GUI->msgbox(-text=>"License is out of date! Please check with TopLinker!");
#    return;
#}

use utf8;
use Encode;
use Data::Dump qw/dump/;
my $Return = 'Done';

my ($Job,$Step) = ($JOB,undef);

###处理step过滤
$PAR->{step_filter} = $PAR->{step_filter} ? $PAR->{step_filter} : '.*';
$PAR->{is_select_lyr} = 'yes' unless $PAR->{is_select_lyr};

my $DrillLayer = $PAR->{drill_layer};
my $MinSMDCopperLine = $PAR->{smd_line};
my $MinBGACopperLine = $PAR->{bga_line};
my $Coverage = $PAR->{coverage};
my $CoverageTol = $PAR->{coverage_tol};
my $BGACopperOpening = $PAR->{bga_copperopen};
my $SpecBGACopperOpening = $PAR->{spec_bga_copperopen};
my $SMDCopperOpening = $PAR->{smd_copperopen};
my $PTHCopperOpening = $PAR->{pth_copperopen};
my $VIACopperOpening = $PAR->{via_copperopen};
my $PADCopperOpening = $PAR->{pad_copperopen};
my $CopperOpening;
my $OptOpening = $PAR->{opt_open};
my $UpdateMaxOpening = $PAR->{update_max_opening};
my $GasketSize = $PAR->{gasket_size};
my $DoSMD = $PAR->{smd};
my $DoPTH = $PAR->{pth};
my $DoVIA = $PAR->{via};
my $DoBGA = $PAR->{bga};
my $DoPAD = $PAR->{pad};
my $KeepGasket = $PAR->{keep_gasket};
my $IgnoreAttr = $PAR->{ignore_attr} || '';
my $IncludeTearDrop = $PAR->{include_teardrop};
my $IncludePad = $PAR->{include_pad}|| 'No';
my $InIgnoreSmdBga = $PAR->{ignore_bgasmd}|| 'No';
my $DeleteSamllArea = $PAR->{delete_samll_area}||'No';
my $SmallAreaOpen = $PAR->{small_area_open}||'0.01';
my $AttrHash = {bga=>$PAR->{bga_attr},smd=>$PAR->{smd_attr}};
my $LaserPadAttr =  $PAR->{laser_pad_attr} || '';
my $SpecificalWarningSuffix = $PAR->{specifical_opening_suffix} || '';
my $BakSuffix = $PAR->{backup_suffix} || '+++';
$PAR->{is_select_lyr} = 'Yes' unless $PAR->{is_select_lyr};

my %TmpLayer = (
    tmp_layer => 'tl_script_tmp_layer',              ###临时中间使用的层
    big_copper_layer => 'tl_script_tmp_layer1',      ###铜面和粗线
    pad_touch_copper => 'tl_script_tmp_layer2',      ###碰到 big_copper_layer 的所有盘
    pad_opening => 'tl_script_tmp_layer3',           ###pad_touch_copper 盘所对应的开窗
    sm_opening => 'tl_script_tmp_layer31',           ###solder mask 层所有东西复制到这里并做contourize
    org_pad_opening => 'tl_script_tmp_layer4',       ###pad_touch_copper 盘所对应的原稿开窗
    opt_big_copper => 'tl_script_tmp_layer5',        ####优化铜面和粗线,来制作缺口和coverage
    correct_sm_opening => 'tl_script_tmp_layer6',    ####制作准确的开窗
    sm_opening_free => 'tl_script_tmp_layer7',       ####制作开窗要的负片层
    npth_layer=> 'tl_script_tmp_layer8',             ####npth drill layer
    sm_less_pad => 'tl_script_tmp_layer9',           ####开窗比盘小 (有一边小就算)
    pad_on_copper_gasket => 'tl_script_tmp_layer10', ####开窗比盘小 (有一边小就算)
    remove_specifical_sm => 'tl_script_tmp_layer11', ####特殊开窗不处理
    all_pad_with_attr => 'tl_script_tmp_layer12',    ####符合条件的所有pad
    sliver_layer => 'tl_script_tmp_layer13',         ####需要优化掉的小细丝层
    smd_bga_pad => 'tl_script_tmp_layer15',          ####smd bga attribute pad
	via_drill_layer => 'tl_script_tmp_layer16',      ####via drill layer
    samll_area_layer=>'tl_script_tmp_layer17',          #####制作去除小面积开窗层
    sm_defined_tmp_layer=>'tl_script_tmp_layer18',          #####临时sm defined层
);

try{
	###Check genesis job name exist or not
	unless ( $Job and  $GEN->isJobExists(job=>$Job) ){
        $Job = $GUI->select_job(
			-title=>'请选择料号',
			-joblist=>[$GEN->getJobList()]
		);
		return 'Cancel' if (! defined $Job or (defined $Job and $Job eq ''));
    }
	
	###open Job
    $GEN->openJob(job=>$Job) unless ($GEN->isJobOpen(job=>$Job));
    
	###check and get work Step name 
	my @steps =  $GEN->getStepList(job=>$Job);
	if ( @steps == 0 ) {
		$GUI->msgbox(-icon=>'error',-text=>'在料号中没有Step存在,你将退出!');
		return 'Cancel';
	}
	elsif (@steps != 1){
        my @tmp_steps = grep(/$PAR->{step_filter}/,@steps);
		if ( @tmp_steps == 0 ) {
            $GUI->msgbox(-icon=>'warning',-text=>'根据脚本参数过滤出来的step不存在,请检查资料或者脚本参数配置!');
			return 'Cancel';
        }
        elsif ( @tmp_steps == 1 ) {
            $Step = $tmp_steps[0];
        }
        else {
            $Step = $GUI->select_step(-title=>'请选择工作Step',
                                      -steplist=>[@tmp_steps],
                                      -selectmode=>'single');
            return 'Cancel' unless ($Step);            
        }
	}
    else {
        $Step = $steps[0];
    }
    
    ###Open step and clear layer
    $GEN->openStep(job=>$Job,name=>$Step);
    $GEN->COM("disp_off");
    $GEN->clearLayers();
    $GEN->affectedLayer(mode=>'all',affected=>'no');
    $GEN->units(type=>'inch');
    ####选择SM层,并寻找对应的外层
    my %matrix=$GEN->getMatrix(job=>$Job,type=>'hash');
    #my @smlayer = $GUI->select_layer(-title=>'Please select solder mask layer to opt Defined pad',
    #                                 -layermatrix=>\%matrix);
    #return 'Cancel' unless ( @smlayer );
    
    my $layers = select_work_layer();
    return $layers if $layers eq 'Cancel';
    my @smlayer = @{$layers};
	
	my %smout;
	foreach my $item ( @smlayer ) {
		if ( $matrix{$item}{side} eq 'top' ) {
			foreach my $layer (keys %matrix) {
				if ( $matrix{$layer}{tl_name} eq 'top' ) {
					$smout{$item} = $layer;
					last;
				}
			}
		}
		elsif ( $matrix{$item}{side} eq 'bottom' ) {
			foreach my $layer (keys %matrix) {
				if ( $matrix{$layer}{tl_name} eq 'bottom' ) {
					$smout{$item} = $layer;
					last;
				}
			}
		}
	}
	
	#####确认外层名字
	my $tmp;
	my $tmplayerhash;
	foreach my $item (keys %matrix) {
		push(@$tmplayerhash,{name=>$item});
	}
	foreach my $item (@smlayer) {
		push(@$tmp,
			{
				name=>$item,
				label=>$item,
				type=>'enum',
				property=>{
					tl_field=>[name=>'text'],
					tl_value_field=>'name',
					tl_data=>$tmplayerhash
				},
				must_field=>1,
				value => $smout{$item} || ''
			}
		);
	}
	if ( ! $GEN->isLayerExists(job=>$Job,layer=>$DrillLayer) ) {
		push(@$tmp,
			{
				name=>'drill',
				label=>'Drill Layer',
				type=>'enum',
				property=>{
					tl_field=>[name=>'text'],
					tl_value_field=>'name',
					tl_data=>$tmplayerhash
				},
				must_field=>1,
				value => $DrillLayer
			}
		);
	}
	my %tmp = $GUI->show_form(
		-title => 'Set Outer Layer of defined SM Layer',
		-items => $tmp
	);
	
    return 'Cancel' unless %tmp;
	if ( $tmp{drill} ) {
		$DrillLayer = delete $tmp{drill};
	}
    
    ###获取补偿值
    #my $out_comp = $IKM->get_jobinfo(-jobid=>$JOB_ID,-jobcategory=>'work',-jobinfo=>'outer_comp_value');
    #my $bga_comp = $out_comp;
    #if( $out_comp ){
    #    my $customer_code = $IKM->select_value(-table=>'pdm_job',-field=>'customer_code',-where=>{id=>$JOB_ID});
    #    if( $customer_code =~ /(1812|1861)/ ){
    #        $bga_comp += 1;
    #    }
    #    else{
    #        $bga_comp += 0.5;
    #    }
    #}
    #$out_comp = $out_comp/2 - 0.5;
    #$bga_comp = $bga_comp/2 - 0.5;
    
    #####confirm parameter
    my $info = [
		{
			name=>'smd',
			label=>'处理SMD盘',
			type=>'enum',
			property=>{
				tl_field=>[name=>'scalar',display_name=>'text'],
				tl_value_field=>'name',
				tl_data=>[
					{name=>'Yes',display_name=>'Yes'},
					{name=>'No',display_name=>'No'}
				]
			},
			must_field=>1,
			remark=>'是否处理SMD盘',
			value => $PAR->{smd},
		},
		{
			name=>'bga',
			label=>'处理BGA盘',
			type=>'enum',
			property=>{
				tl_field=>[name=>'scalar',display_name=>'text'],
				tl_value_field=>'name',
				tl_data=>[
					{name=>'Yes',display_name=>'Yes'},
					{name=>'No',display_name=>'No'}
				]
			},
			must_field=>1,
			remark=>'是否处理BGA盘',
			value => $PAR->{bga},
		},
		{
			name=>'pth',
			label=>'处理pth 孔盘',
			type=>'enum',
			property=>{
				tl_field=>[name=>'scalar',display_name=>'text'],
				tl_value_field=>'name',
				tl_data=>[
					{name=>'Yes',display_name=>'Yes'},
					{name=>'No',display_name=>'No'}
				]
			},
			must_field=>1,
			remark=>'是否处理PTH所对应的盘',
			value => $PAR->{pth},
		},
		{
			name=>'via',
			label=>'处理via 孔盘',
			type=>'enum',
			property=>{
				tl_field=>[name=>'scalar',display_name=>'text'],
				tl_value_field=>'name',
				tl_data=>[
					{name=>'Yes',display_name=>'Yes'},
					{name=>'No',display_name=>'No'}
				]
			},
			must_field=>1,
			remark=>'是否处理VIA所对应的盘',
			value => $PAR->{via},
		},
		{
			name=>'pad',
			label=>'处理其它盘',
			type=>'enum',
			property=>{
				tl_field=>[name=>'scalar',display_name=>'text'],
				tl_value_field=>'name',
				tl_data=>[
					{name=>'Yes',display_name=>'Yes'},
					{name=>'No',display_name=>'No'}
				]
			},
			must_field=>1,
			remark=>'是否处理除SMD,BGA,和PTH孔对应盘以外的所有pad',
			value => $PAR->{pad},
		},
		{
			name=>'smd_line',
			label=>'SMD认为是铜面的最小线(mil)',
			type=>'string',
			must_field=>1,
			remark=>'',
			value => $PAR->{smd_line},
		},
		{
			name=>'bga_line',
			label=>'BGA认为是铜面的最小线(mil)',
			type=>'string',
			must_field=>1,
			remark=>'',
			value => $PAR->{bga_line},
		},
		{
			name=>'coverage',
			label=>'最小Coverage(mil)',
			type=>'string',
			must_field=>1,
			remark=>'需去除Coverage Tol',
			value => $PAR->{coverage},
		},
		{
			name=>'coverage_tol',
			label=>'Coverage Tol(mil)',
			type=>'string',
			must_field=>1,
			remark=>'主要用于铜面比线路pad稍微大一点时,忽略宽度的值,会纳入最小Coverage计算',
			value => $PAR->{coverage_tol},
		},
		{
			name=>'bga_copperopen',
			label=>'BGA铜面上单边开窗(mil)',
			type=>'string',
			must_field=>1,
			remark=>'',
			value => $PAR->{bga_copperopen},
		},
		{
			name=>'spec_bga_copperopen',
			label=>'特殊BGA铜面上单边开窗(mil)',
			type=>'string',
			must_field=>1,
			remark=>'',
			value => $PAR->{spec_bga_copperopen},
		},
        {
			name=>'smd_copperopen',
			label=>'SMD铜面上单边开窗(mil)',
			type=>'string',
			must_field=>1,
			remark=>'',
			value => $PAR->{smd_copperopen},
		},
        {
			name=>'pth_copperopen',
			label=>'PTH盘铜面上单边开窗(mil)',
			type=>'string',
			must_field=>1,
			remark=>'',
			value => $PAR->{pth_copperopen},
		},
		{
			name=>'via_copperopen',
			label=>'VIA盘铜面上单边开窗(mil)',
			type=>'string',
			must_field=>1,
			remark=>'',
			value => $PAR->{via_copperopen},
		},
        {
			name=>'pad_copperopen',
			label=>'其他盘铜面上单边开窗(mil)',
			type=>'string',
			must_field=>1,
			remark=>'',
			value => $PAR->{pad_copperopen},
		},
		{
			name=>'opt_open',
			label=>'正常最优单边开窗(mil)',
			type=>'string',
			must_field=>1,
			remark=>'',
			value => $PAR->{opt_open},
		},
		{
			name=>'update_max_opening',
			label=>'允许优化的单边最大开窗(mil)',
			type=>'string',
			must_field=>1,
			remark=>'pad单边放大这个值后,开窗在里面的才优化',
			value => $PAR->{update_max_opening},
		},
        
		{
			name=>'include_teardrop',
			label=>'大铜面包含.tear_drop',
			type=>'enum',
			property=>{
				tl_field=>[name=>'scalar',display_name=>'text'],
				tl_value_field=>'name',
				tl_data=>[
					{name=>'Yes',display_name=>'Yes'},
					{name=>'No',display_name=>'No'}
				]
			},
			must_field=>1,
			remark=>'碰到大铜面或者粗线的.tear_drop是否也当成大铜面处理',
			value => $PAR->{include_teardrop},
		},
		{
			name=>'keep_gasket',
			label=>'是否保证Gasket',
			type=>'enum',
			property=>{
				tl_field=>[name=>'scalar',display_name=>'text'],
				tl_value_field=>'name',
				tl_data=>[
					{name=>'Yes',display_name=>'Yes'},
					{name=>'No',display_name=>'No'}
				]
			},
			must_field=>1,
			remark=>'是否保证开窗下面的垫圈',
			value => $PAR->{keep_gasket},
		},
		{
			name=>'gasket_size',
			label=>'开窗gasket最小(mil)',
			type=>'string',
			must_field=>1,
			remark=>'为了保证完全落于铜面的开窗大小,对于靠在边上的下面加垫圈',
			value => $PAR->{gasket_size},
		},
	];
    my %info = $GUI->show_form(
		-title=>'请设置缩铜面Pad参数',
		-items=>$info);
    return 'Cancel' unless %info;
    $MinSMDCopperLine = $info{smd_line};
    $MinBGACopperLine = $info{bga_line};
    $Coverage = $info{coverage};
    $CoverageTol = $info{coverage_tol};
    $BGACopperOpening = $info{bga_copperopen};
    $SMDCopperOpening = $info{smd_copperopen};
    $PTHCopperOpening = $info{pth_copperopen};
    $VIACopperOpening = $info{via_copperopen};
    $PADCopperOpening = $info{pad_copperopen};
    $OptOpening = eval($info{opt_open});
	$GasketSize = $info{gasket_size};
    $DoSMD = $info{smd};
    $DoBGA = $info{bga};
    $DoPTH = $info{pth};
    $DoVIA = $info{via};
    $DoPAD = $info{pad};
    $IncludeTearDrop = $info{include_teardrop};
    $KeepGasket = $info{keep_gasket};
    $UpdateMaxOpening = $info{update_max_opening};
	
    %tmp = reverse %tmp;
    foreach my $layer (keys %tmp) {
        my $ref_layer = $tmp{$layer}.'_ref';
        if ( $GEN->isLayerExists(job=>$Job,layer=>$ref_layer) ) {
            $GEN->workLayer(name=>$ref_layer,number=>1);
            $GEN->selDelete();
        }
        else {
            $GEN->createLayer(job=>$Job,layer=>$ref_layer);
        }
        $GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$tmp{$layer},dest_layer=>$tmp{$layer}.$BakSuffix);
        $GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$layer,dest_layer=>$layer.$BakSuffix);

        
        $GEN->workLayer(name=>$tmp{$layer},number=>1);
        $GEN->selectByFilter(attribute=>[{attribute=>'.string',text=>'sm_defined_pad_shave'}]);
		$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
		##移除via
        $GEN->selectByFilter(attribute=>[{attribute=>'.drill',option=>'via'}],polarity=>'positive');
		$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
        
        my $sm_tmp_bk = $tmp{$layer}.'_tl_script_bk';
        $GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$tmp{$layer},dest_layer=>$sm_tmp_bk);
        
        #$GEN->selectByFilter(attribute=>[{attribute=>'.shave'}]);
        $GEN->selectByFilter(polarity=>'negative');
		$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );


        $GEN->workLayer(name=>$layer,number=>1);
        $GEN->selectByFilter(attribute=>[{attribute=>'.string',text=>'smdef_gasket'}]);
        $GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
		_deleteLayer(layer=>[$tmp{$layer}.$SpecificalWarningSuffix]);
        

        foreach my $item ('smd','bga','pth','via','pad') {#'smd','bga','pth','via','pad'
            next unless ( defined $info{$item} and $info{$item} eq 'Yes' );
            my $Coverage_tmp = $Coverage;
            my $CoverageTol_tmp = $CoverageTol; 
            
            if ( $item eq 'smd' or $item eq 'bga' ) {
                    next unless ( $AttrHash->{$item} );
            }
            _deleteLayer(layer=>[values %TmpLayer]);
            
            if ( $item eq 'smd' ) {
                $CopperOpening = $SMDCopperOpening;
            }
            elsif ( $item eq 'bga' ) {
                $CopperOpening = $BGACopperOpening;
            }
            elsif ( $item eq 'pth' ) {
                $CopperOpening = $PTHCopperOpening;
            }
			elsif ( $item eq 'via' ) {
                $CopperOpening = $VIACopperOpening;
            }
            elsif ( $item eq 'pad' ) {
                $CopperOpening = $PADCopperOpening;
            }
            
            ####制作npth and via drill layer
            $GEN->createLayer(job=>$Job,layer=>$TmpLayer{npth_layer});
            $GEN->workLayer(name=>$DrillLayer,number=>1);
            $GEN->selectByFilter(attribute=>[{attribute=>'.drill',option=>'non_plated'}]);
            if ( $GEN->getSelectCount() > 0 ) {
                $GEN->selCopyOther(target_layer=>$TmpLayer{npth_layer});
            }
			$GEN->selectByFilter(attribute=>[{attribute=>'.drill',option=>'via'}]);
            if ( $GEN->getSelectCount() > 0 ) {
                $GEN->selCopyOther(target_layer=>$TmpLayer{via_drill_layer});
            }

			
            ####制作铜面和粗线层(有碰到的.tear_drop也包括) 到辅助层 big_copper_layer
            $GEN->workLayer(name=>$layer,number=>1);
            $GEN->selectByFilter(feat_types=>'surface');
            $GEN->selectByFilter(polarity=>'negative');


            my $tmp_line = $MinSMDCopperLine;
            if ( $item eq 'bga' ) {
                $tmp_line = $MinBGACopperLine;
            }
            my %symhist = $GEN->getLayerSymsHist(job=>$Job,step=>$Step,layer=>$layer);
            foreach my $sym (keys %symhist) {
                if ( $sym =~ /^(r|s)[0-9]+\.?[0-9]*$/ and $symhist{$sym}{size} >= $tmp_line ) {
                    $GEN->selectByFilter(include_syms=>$sym,
                                         feat_types=>'line\;arc',
                                         polarity=>'positive');
                }
            }
			if ( $IncludeTearDrop eq 'No' ) {
				$GEN->selectByFilter(
					attribute=>'.tear_drop',
					operation=>'unselect'
				);
			}
            
            if ( $GEN->getSelectCount() > 0 ) {
                $GEN->selCopyOther(target_layer=>$TmpLayer{big_copper_layer});
            }
            else {
                next;
            }
            
            if ( $IncludeTearDrop eq 'Yes' ) {
                    $GEN->selRefFeat(
                        layers=>$TmpLayer{big_copper_layer},
                        use=>'filter',
                        mode=>'touch',
                        f_types=>'line\;arc',
                        polarity=>'positive',
                        filter=>{
                            filter_name => 'popup',
                            attribute=>[{attribute=>'.tear_drop'}],
                        }
                    );
                    if ( $GEN->getSelectCount() > 0 ) {
                        $GEN->selCopyOther(target_layer=>$TmpLayer{big_copper_layer});
                    }
            }

			if( $IncludePad eq 'Yes' ){
				$GEN->attributeReset();
				$GEN->COM('filter_reset',filter_name=>'popup');
				$GEN->selRefFeat(
					layers=>$TmpLayer{big_copper_layer},
					use=>'filter',
					mode=>'touch',
					f_types=>'line\;arc',
					polarity=>'positive',
                    filter=>{
                        filter_name => 'popup',
                        feat_types=>'pad',
                        polarity=>'positive',
                    }
				);
				if ( $GEN->getSelectCount() > 0 ) {
					my $include_pad_lyr = '__include_pad_lyr__tl_script__';
					$GEN->createLayer(job=>$Job,layer=>$include_pad_lyr,conext=>'misc',type=>'document',delete_exists =>'yes');
					$GEN->selCopyOther(target_layer=>$include_pad_lyr);
					$GEN->workLayer(name=>$include_pad_lyr,number=>1);
					$GEN->attributeReset();
					$GEN->COM('filter_reset',filter_name=>'popup');
                    $GEN->selRefFeat(
                        layers=>$tmp{$layer},
                        use=>'filter',
                        mode=>'disjoint'
                    );
                    $GEN->selRefFeat(
                        layers=>$tmp{$layer},
                        use=>'filter',
                        mode=>'cover'
                    );
                    $GEN->selRefFeat(
                        layers=>$tmp{$layer},
                        use=>'filter',
                        mode=>'include'
                    );
					$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
                    $GEN->workLayer(name=>$include_pad_lyr,number=>1);
                    
                    
					$GEN->COM("sel_all_feat");
					if ( $GEN->getSelectCount() > 0 ){
                        $GEN->selCopyOther(target_layer=>$TmpLayer{big_copper_layer});
                        $GEN->workLayer(name=>$layer,number=>1);
                        $GEN->selectByFilter(polarity=>'negative');
                        $GEN->selCopyOther(target_layer=>$TmpLayer{big_copper_layer}) if ( $GEN->getSelectCount() > 0 );
                    }
					 _deleteLayer(layer=>[$include_pad_lyr]);
				}
			}

            $GEN->workLayer(name=>$TmpLayer{big_copper_layer},number=>1);
            $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
            $GEN->selectByFilter();
            if ( $GEN->getSelectCount() == 1 ) {
                    $GEN->COM('sel_decompose',overlap=>'yes');
                    #$GEN->selContourize();
                    $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
            }
            else {
                    $GEN->selClearFeature();
            }

            #####选择有碰到大铜面的盘到临时层 pad_touch_copper
            #####如果是pth会去除smd和bga
            #####如果是smd会去除bga
            my $tmp_work_layer = $layer.'_tmp_script__';
            $GEN->copyLayer(source_job=>$Job,
                            source_step=>$Step,
                            source_layer=>$layer,
                            dest_layer=>$tmp_work_layer,
                            mode=>'replace', #append/replace
                            invert=>'no') ;#|'yes'
            $GEN->workLayer(name=>$tmp_work_layer,number=>1);
            $GEN->attributeReset();
            $GEN->COM('filter_reset',filter_name=>'popup');
            $GEN->selectByFilter(
                 attribute=>[{attribute=>'tl_string',text=>'pad_touch_copper_tmp_attr'}],
            );
            if ($GEN->getSelectCount() > 0) {
                #$GEN->COM( "sel_delete_atr,attributes=tl_string,text=pad_touch_copper_tmp_attr" );
				$GEN->COM( "sel_delete_atr,attributes=tl_string" );
            }
            if ($item eq 'pad') {
                #if ( $GEN->isLayerExists(job=>$Job,layer=>$TmpLayer{via_drill_layer}) ) {
                    $GEN->COM("filter_reset,filter_name=popup");
                    $GEN->COM("filter_set,filter_name=popup,update_popup=no,feat_types=pad,polarity=positive");
                    $GEN->COM("sel_ref_feat,layers=$TmpLayer{via_drill_layer},use=filter,mode=touch,pads_as=shape,f_types=pad,polarity=positive,include_syms=,exclude_syms=");
                    $GEN->COM("filter_reset,filter_name=popup");
                    $GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
                #}
            }
            $GEN->selectByFilter(attribute=>$AttrHash->{bga});
            $GEN->selCopyOther(target_layer=>$TmpLayer{smd_bga_pad}) if ( $GEN->getSelectCount() > 0 );
            $GEN->selectByFilter(attribute=>$AttrHash->{smd}); 
            $GEN->selCopyOther(target_layer=>$TmpLayer{smd_bga_pad}) if ( $GEN->getSelectCount() > 0 );         
            if ( $item eq 'pth' or $item eq 'pad' or $item eq 'via' ) {
                $GEN->selRefFeat(
                    layers=>$TmpLayer{big_copper_layer},
                    use=>'filter',
                    mode=>'touch',
                    filter=>{
                        filter_name => 'popup',
                        feat_types=>'pad',
                        polarity=>'positive',
                    }
                );
            }
            else {
                $GEN->selRefFeat(
                    layers=>$TmpLayer{big_copper_layer},
                    use=>'filter',
                    mode=>'touch',
                    filter=>{
                        filter_name => 'popup',
                        attribute=> $AttrHash->{$item}
                    }
                );
            }
            
            if ( $item eq 'smd' ) {
                $GEN->selectByFilter(
                    attribute=>$AttrHash->{bga},
                    operation=>'unselect'
                );               
            }
            elsif ( $item eq 'pth' or $item eq 'pad' or $item eq 'via' ) {
                $GEN->selectByFilter(
                    attribute=>$AttrHash->{bga},
                    operation=>'unselect'
                );
                $GEN->selectByFilter(
                    attribute=>$AttrHash->{smd},
                    operation=>'unselect'
                );
            }
            
            if ( $GEN->getSelectCount() > 0 ) {
                $GEN->selAddAttr(attribute=>[{attribute=>'tl_string',text=>'pad_touch_copper_tmp_attr'}]);
                $GEN->selectByFilter(
                     attribute=>[{attribute=>'tl_string',text=>'pad_touch_copper_tmp_attr'}],
                );
                if ( $item eq 'pth' or $item eq 'pad' or $item eq 'via' ) {
                    $GEN->selRefFeat(
                        use=>'select',
                        mode=>'touch',
                        filter=>{
                            filter_name => 'popup',
                            feat_types=>'pad',
                            polarity=>'positive',
                        }
                    );
                    $GEN->selectByFilter(
                        attribute=>$AttrHash->{bga},
                        operation=>'unselect'
                    );
                    $GEN->selectByFilter(
                        attribute=>$AttrHash->{smd},
                        operation=>'unselect'
                    );
                }else{
                    $GEN->selRefFeat(
                        use=>'select',
                        mode=>'touch',
                        filter=>{
                            polarity=>'positive',
                            attribute=>$AttrHash->{$item},
                        }
                    );
                    $GEN->selectByFilter(
                        attribute=>$AttrHash->{bga},
                        operation=>'unselect'
                    );  
                }
                $GEN->selAddAttr(attribute=>[{attribute=>'tl_string',text=>'pad_touch_copper_tmp_attr'}])if ( $GEN->getSelectCount() > 0 );
                $GEN->selectByFilter(
                     attribute=>[{attribute=>'tl_string',text=>'pad_touch_copper_tmp_attr'}],
                );

                
                $GEN->selCopyOther(target_layer=>$TmpLayer{pad_touch_copper});
                $GEN->workLayer(name=>$TmpLayer{pad_touch_copper},number=>1);
                if ( $item eq 'pth' or $item eq 'via' ) {
                    $GEN->selRefFeat(
                        layers=>$DrillLayer,
                        use=>'filter',
                        mode=>'disjoint'
                    );
                    $GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
					if ( $GEN->isLayerExists(job=>$Job,layer=>$TmpLayer{via_drill_layer}) ) {
						if ( $item eq 'pth' ) {
							$GEN->selRefFeat(
								layers=>$TmpLayer{via_drill_layer},
								use=>'filter',
								mode=>'touch'
							);
							$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
						}
						elsif ( $item eq 'via' ) {
							$GEN->selRefFeat(
								layers=>$TmpLayer{via_drill_layer},
								use=>'filter',
								mode=>'disjoint'
							);
							$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
						}
					}
                }
                elsif ( $item eq 'pad' ) {
                    #$GEN->selRefFeat(
                    #    layers=>$DrillLayer,
                    #    use=>'filter',
                    #    mode=>'touch'
                    #);
                    #$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
					$GEN->COM("filter_atr_set,filter_name=ref_select,condition=yes,attribute=.drill,option=plated");
                    $GEN->selRefFeat(
                   	     layers=>$DrillLayer,
                         use=>'filter',
                         mode=>'touch'
                    );
                    $GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
					$GEN->COM("filter_atr_reset,filter_name=ref_select");
                    
                }
                if ( ($item eq 'pth' or $item eq 'pad' or $item eq 'via') and ( $GEN->isLayerExists(job=>$Job,layer=>$TmpLayer{smd_bga_pad}) )  and $InIgnoreSmdBga eq 'No') {
                    $GEN->selRefFeat(
                        layers=>$TmpLayer{smd_bga_pad},
                        use=>'filter',
                        mode=>'touch'
                    );
                    $GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
                }
                $GEN->selRefFeat(
                    layers=>$TmpLayer{npth_layer},
                    use=>'filter',
                    mode=>'touch'
                );
                $GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
            }
            else {
                next;
            }
            ###去除laser Pad
            $GEN->workLayer(name=>$TmpLayer{pad_touch_copper},number=>1);
            if ( $LaserPadAttr ) {
                $GEN->selectByFilter(
                    feat_types=>'pad',
                    polarity=>'positive',
                    attribute=>$LaserPadAttr
                );
                $GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
            }
			
            ####制作符合条件的所有pad 到辅助层 all_pad_with_attr
            $GEN->workLayer(name=>$layer,number=>1);
            $GEN->attributeReset();
            $GEN->COM('filter_reset',filter_name=>'popup');
            if ( $item eq 'pth' or $item eq 'via' ) {
                $GEN->selRefFeat(
                    layers=>$DrillLayer,
                    use=>'filter',
                    mode=>'touch',
                    filter=>{
                        filter_name => 'popup',
                        feat_types=>'pad'
                    }
                );
            }
            elsif ( $item eq 'pad' ) {
                #$GEN->selRefFeat(
                #    layers=>$DrillLayer,
                #    use=>'filter',
                #    mode=>'touch',
                #    filter=>{
                #        filter_name => 'popup',
                #        feat_types=>'pad'
                #    }
                #);
			
                $GEN->COM("filter_atr_set,filter_name=ref_select,condition=yes,attribute=.drill,option=plated");
                $GEN->selRefFeat(
                               layers=>$DrillLayer,
                               use=>'filter',
                               mode=>'disjoint',
                               filter=>{
                                       filter_name => 'popup',
                                       feat_types=>'pad'
                               }
                );
                $GEN->COM("filter_atr_reset,filter_name=ref_select");
            }
            else {
                $GEN->selectByFilter(
                    feat_types=>'pad',
                    polarity=>'positive',
                    attribute=>$AttrHash->{$item}
                );
            }
            
            if ( $item eq 'smd' ) {
                $GEN->selectByFilter(
                    attribute=>$AttrHash->{bga},
                    operation=>'unselect'
                );               
            }
            elsif ( $item eq 'pth' or $item eq 'pad' ) {
                $GEN->selectByFilter(
                    attribute=>$AttrHash->{bga},
                    operation=>'unselect'
                );
                $GEN->selectByFilter(
                    attribute=>$AttrHash->{smd},
                    operation=>'unselect'
                );
            }
            if ( $GEN->getSelectCount() > 0 ) {
                $GEN->selCopyOther(target_layer=>$TmpLayer{all_pad_with_attr});
                $GEN->workLayer(name=>$TmpLayer{all_pad_with_attr},number=>1);
                $GEN->selRefFeat(
                    layers=>$TmpLayer{npth_layer},
                    use=>'filter',
                    mode=>'touch'
                );
                $GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
				if ( $GEN->isLayerExists(job=>$Job,layer=>$TmpLayer{via_drill_layer}) ) {
					if ( $item eq 'pth' ) {
						$GEN->selRefFeat(
							layers=>$TmpLayer{via_drill_layer},
							use=>'filter',
							mode=>'touch'
						);
						$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
					}
					elsif ( $item eq 'via' ) {
						$GEN->selRefFeat(
							layers=>$TmpLayer{via_drill_layer},
							use=>'filter',
							mode=>'disjoint'
						);
						$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
					}
				}

                if ( $GEN->isLayerExists(job=>$Job,layer=>$TmpLayer{smd_bga_pad}) and ( $item eq 'pth' or $item eq 'via' or $item eq 'pad' ) and $InIgnoreSmdBga eq 'No') {
                    $GEN->selRefFeat(
                        layers=>$TmpLayer{smd_bga_pad},
                        use=>'filter',
                        mode=>'touch'
                    );
                    $GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
                }
            }
            else {
                next;
            }
            ###去除laser Pad
            $GEN->workLayer(name=>$TmpLayer{all_pad_with_attr},number=>1);
            if ( $LaserPadAttr ) {
				$GEN->selectByFilter(
							feat_types=>'pad',
							polarity=>'positive',
							attribute=>$LaserPadAttr
				);
				$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
			}
			
            
            ####制作碰到大铜面的pad所对应的开窗到临时层pad_opening
            $GEN->workLayer(name=>$tmp{$layer},number=>1);
            $GEN->selCopyOther(target_layer=>$TmpLayer{pad_opening});
            
            
            $GEN->workLayer(name=>$TmpLayer{pad_opening},number=>1);
            $GEN->selectByFilter(feat_types=>'surface');
            $GEN->selectByFilter(polarity=>'negative');##删除所有负片
            $GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
            #remove npth opening
            $GEN->selRefFeat(
                layers=>$TmpLayer{npth_layer},
                use=>'filter',
                mode=>'touch'
            );
            $GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
            $GEN->selRefFeat(
                layers=>$TmpLayer{pad_touch_copper},
                use=>'filter',
                mode=>'disjoint'
            );
            
            $GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
            
			####去除客户定义不需要处理的开窗
			if ( $IgnoreAttr ) {
				$GEN->selectByFilter(attribute=>$IgnoreAttr);
				$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
			}
            #$GEN->selContourize();
			$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
			$GEN->selectByFilter();
			if ( $GEN->getSelectCount() == 1 ) {
				$GEN->COM('sel_decompose',overlap=>'yes');
				#$GEN->selContourize();
				$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
			}
			else {
				$GEN->selClearFeature();
			}

            ###去除特殊开窗
            $GEN->workLayer(name=>$TmpLayer{pad_touch_copper},number=>1);
            $GEN->selCopyOther(target_layer=>$TmpLayer{tmp_layer});
            $GEN->workLayer(name=>$TmpLayer{tmp_layer},number=>1);
            $GEN->COM('sel_resize',size=>$UpdateMaxOpening*3,corner_ctl=>'no');

            $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
            $GEN->selectByFilter();
            if ( $GEN->getSelectCount() == 1 ) {
                    $GEN->COM('sel_decompose',overlap=>'yes');
                    #$GEN->selContourize();
                    $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
            }
            else {
                    $GEN->selClearFeature();
            }
   
            $GEN->workLayer(name=>$TmpLayer{pad_opening},number=>1);
            $GEN->selRefFeat(
                layers=>$TmpLayer{tmp_layer},
                use=>'filter',
                mode=>'cover'
            );
            
            #$GEN->COM('disp_on');
            $GEN->selReverse();
            if ( $GEN->getSelectCount() > 0 )  {
                $GEN->selCopyOther(target_layer=>$TmpLayer{remove_specifical_sm});
                ##2018-3-23修复如果防焊开窗ring本来满足要求,就会放到报警层而不制作smdefined的问题  -- start
                #$GEN->workLayer(name=>$TmpLayer{remove_specifical_sm},number=>1);
                #$GEN->selRefFeat(
                #    layers=>$TmpLayer{tmp_layer},
                #    use=>'filter',
                #    mode=>'include'
                #);
                #$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
                ##2018-3-23 -- end
                ##
                $GEN->workLayer(name=>$TmpLayer{pad_opening},number=>1);
                $GEN->selRefFeat(
                    layers=>$TmpLayer{remove_specifical_sm},
                    use=>'filter',
                    mode=>'touch'
                );
                $GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
				if ( $SpecificalWarningSuffix ) {
	                $GEN->workLayer(name=>$TmpLayer{remove_specifical_sm},number=>1);
	                $GEN->selCopyOther(target_layer=>$tmp{$layer}.$SpecificalWarningSuffix);
	            }
            }
            
            
            #$GEN->PAUSE('tttt');
            _deleteLayer(layer=>[$TmpLayer{tmp_layer}]);
			
            ####去除没有被覆盖在开窗里面的pad
            $GEN->workLayer(name=>$TmpLayer{pad_touch_copper},number=>1);
                $GEN->selRefFeat(
                layers=>$TmpLayer{pad_opening},
                use=>'filter',
                mode=>'cover'
            );
            $GEN->selReverse();
            $GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
			
            ####所有SM开窗到临时层sm_opening
            $GEN->workLayer(name=>$tmp{$layer},number=>1);
            $GEN->selCopyOther(target_layer=>$TmpLayer{sm_opening});
            $GEN->workLayer(name=>$TmpLayer{sm_opening},number=>1);
            #$GEN->selContourize();
            $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
            $GEN->selectByFilter();
            if ( $GEN->getSelectCount() == 1 ) {
                    $GEN->COM('sel_decompose',overlap=>'yes');
                    #$GEN->selContourize();
                    $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
            }
            else {
					$GEN->selClearFeature();
			}
			
            ###制作开窗比pad小的到临时层 sm_less_pad
            $GEN->workLayer(name=>$TmpLayer{all_pad_with_attr},number=>1);
            $GEN->selCopyOther(target_layer=>$TmpLayer{tmp_layer});
            $GEN->workLayer(name=>$TmpLayer{tmp_layer},number=>1);
           #$GEN->selContourize();
			$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
			$GEN->selectByFilter();
			if ( $GEN->getSelectCount() == 1 ) {
				$GEN->COM('sel_decompose',overlap=>'yes');
				#$GEN->selContourize();
				$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
			}
			else {
				$GEN->selClearFeature();
			}
            $GEN->workLayer(name=>$tmp{$layer},number=>1);
            $GEN->selRefFeat(
                layers=>$TmpLayer{tmp_layer},
                use=>'filter',
                mode=>'include'
            );
            $GEN->selReverse();
            if ( $GEN->getSelectCount() > 0 ) {
                $GEN->selCopyOther(target_layer=>$TmpLayer{sm_less_pad});
                $GEN->workLayer(name=>$TmpLayer{sm_less_pad},number=>1);
                $GEN->selRefFeat(
                    layers=>$TmpLayer{tmp_layer},
                    use=>'filter',
                    mode=>'cover'
                );
                $GEN->selReverse();
                $GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
            }
            
            _deleteLayer(layer=>[$TmpLayer{tmp_layer}]);
            
            ###制作正式层上开窗比pad小的情况
            if ( $GEN->isLayerExists(job=>$Job,layer=>$TmpLayer{sm_less_pad}) and $PAR->{make_sm_less_pad} eq 'Yes') {
                $GEN->workLayer(name=>$tmp{$layer},number=>1);
                $GEN->selRefFeat(
                    layers=>$TmpLayer{sm_less_pad},
                    use=>'filter',
                    mode=>'cover'
                );
                $GEN->selectByFilter(
                    attribute=>[{attribute=>'.string',text=>'smdefpad_sm'}],
                    operation=>'unselect'
                );
				
				####去除客户定义不需要处理的开窗
				if ( $IgnoreAttr ) {
					$GEN->selectByFilter(attribute=>$IgnoreAttr,
										 operation=>'unselect');
				}
                if ( $GEN->getSelectCount() > 0 ) {
                    $GEN->selCopyOther(target_layer=>$TmpLayer{tmp_layer});
                    $GEN->selRefFeat(
                        layers=>$TmpLayer{tmp_layer},
                        use=>'filter',
                        mode=>'cover'
                    );
                    $GEN->selAddAttr(attribute=>[{attribute=>'.string',text=>'smdefpad_sm_'.$item},'smdefpad_sm']) if ( $GEN->getSelectCount() > 0 );
                    $GEN->selectByFilter(attribute=>[{attribute=>'.string',text=>'smdefpad_sm_'.$item}]);
                    if ( $GEN->getSelectCount() > 0 ) {
                        $GEN->selCopyOther(target_layer=>$ref_layer);
                    }
                    $GEN->selectByFilter(attribute=>[{attribute=>'.string',text=>'smdefpad_sm_'.$item}]);
                    $GEN->COM('sel_resize',size=>$CopperOpening*2,corner_ctl=>'no') if ( $GEN->getSelectCount() > 0 );
                    $GEN->workLayer(name=>$TmpLayer{pad_opening},number=>1);
                    $GEN->selRefFeat(
                        layers=>$TmpLayer{tmp_layer},
                        use=>'filter',
                        mode=>'touch'
                    );
                    $GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
                    $GEN->workLayer(name=>$TmpLayer{pad_touch_copper},number=>1);
                    $GEN->selRefFeat(
                        layers=>$TmpLayer{tmp_layer},
                        use=>'filter',
                        mode=>'touch'
                    );
                    $GEN->workLayer(name=>$TmpLayer{all_pad_with_attr},number=>1);
                    $GEN->selRefFeat(
                        layers=>$TmpLayer{tmp_layer},
                        use=>'filter',
                        mode=>'touch'
                    );
                    $GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
                    _deleteLayer(layer=>[$TmpLayer{tmp_layer}]);
                }
            }
			
            ####gaster 制作(copy 外层pad加大(gasketsize+$CopperOpening)*2 到当前层为surface)
			$GEN->workLayer(name=>$TmpLayer{pad_touch_copper},number=>1);
			$GEN->selRefFeat(
				layers=>$TmpLayer{big_copper_layer},
				use=>'filter',
				mode=>'cover'
			);
			if ( $GEN->getSelectCount() > 0 ) {
				$GEN->selCopyOther(target_layer=>$TmpLayer{tmp_layer});
				$GEN->workLayer(name=>$TmpLayer{tmp_layer},number=>1);
				$GEN->selRefFeat(
					layers=>$TmpLayer{pad_opening},
					use=>'filter',
					mode=>'cover'
				);
				if ( $GEN->getSelectCount() > 0 ) {
					$GEN->selCopyOther(target_layer=>$TmpLayer{pad_on_copper_gasket});
				}
			}
			_deleteLayer(layer=>[$TmpLayer{tmp_layer}]);
            if ( $KeepGasket eq 'Yes' and $GEN->isLayerExists(job=>$Job,layer=>$TmpLayer{pad_on_copper_gasket}) ) {
				$GEN->workLayer(name=>$TmpLayer{pad_on_copper_gasket},number=>1);
				$GEN->COM('sel_resize',size=>($GasketSize+$CopperOpening)*2,corner_ctl=>'no');
				$GEN->selAddAttr(attribute=>['gasket',{attribute=>'.string',text=>'smdef_gasket'}]);
				$GEN->selCopyOther(target_layer=>$layer);
				$GEN->selCopyOther(target_layer=>$TmpLayer{big_copper_layer});
				$GEN->workLayer(name=>$TmpLayer{big_copper_layer},number=>1);
				#$GEN->selContourize();
				$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
				$GEN->selectByFilter();
				if ( $GEN->getSelectCount() == 1 ) {
					$GEN->COM('sel_decompose',overlap=>'yes');
					#$GEN->selContourize();
					$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
				}
				else {
					$GEN->selClearFeature();
				}
            }
            
            ####开窗不足最优的情况下最优化开窗
            $GEN->workLayer(name=>$TmpLayer{pad_touch_copper},number=>1);
            $GEN->selCopyOther(target_layer=>$TmpLayer{tmp_layer});
            $GEN->workLayer(name=>$TmpLayer{tmp_layer},number=>1);
            if ( ref $OptOpening eq 'ARRAY' ) {
                my %symhist = $GEN->getLayerSymsHist(job=>$Job,step=>$Step,layer=>$TmpLayer{tmp_layer});
                foreach my $item (sort { $symhist{$b}{size} <=> $symhist{a}{size} } keys %symhist) {
                    my $size = $symhist{$item}{size};
                    if ( ! $size ) {
                        $size = ($symhist{$item}{width} < $symhist{$item}{length}) ? $symhist{$item}{width} : $symhist{$item}{length};
                    }
                    my $cmp;
                    foreach my $v (@$OptOpening) {
                        if ( $size ) {
                            next if ( $v->{type} eq 'others' );
                            if ( $size > $v->{min} and $size <= $v->{max} ) {
                                $cmp = $v->{cmp};
                                last;
                            }
                        }
                        else {
                            if ( $v->{type} eq 'others' ) {
                                $cmp = $v->{cmp};
                                last;
                            }
                        }
                    }
                    if ( $cmp ) {
                        $GEN->selectByFilter(include_syms=>$item);
                        $GEN->COM('sel_resize',size=>$cmp*2,corner_ctl=>'no') if ( $GEN->getSelectCount() > 0 );
                    }
                    else {
                        $GUI->msgbox(-icon=>'error',-text=>"symbol $item 找不到最优开窗大小!");
                        return 'Error';
                    }
                }
            }
            else {
                $GEN->COM('sel_resize',size=>$OptOpening*2,corner_ctl=>'no');
            }
            $GEN->selRefFeat(
                layers=>$TmpLayer{pad_opening},
                use=>'filter',
                mode=>'include'
            );
            $GEN->selReverse();
            $GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
            $GEN->workLayer(name=>$tmp{$layer},number=>1);
            $GEN->selRefFeat(
                layers=>$TmpLayer{tmp_layer},
                use=>'filter',
                mode=>'cover'
            );
            $GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
            $GEN->workLayer(name=>$TmpLayer{tmp_layer},number=>1);
            $GEN->selCopyOther(target_layer=>$tmp{$layer});
            $GEN->selCopyOther(target_layer=>$TmpLayer{pad_opening});
            $GEN->selCopyOther(target_layer=>$TmpLayer{sm_opening});
            $GEN->workLayer(name=>$TmpLayer{pad_opening},number=>1);
            
            #$GEN->selContourize();
			$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
			$GEN->selectByFilter();
			if ( $GEN->getSelectCount() == 1 ) {
				$GEN->COM('sel_decompose',overlap=>'yes');
				#$GEN->selContourize();
				$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
			}
			else {
				$GEN->selClearFeature();
			}
            $GEN->workLayer(name=>$TmpLayer{sm_opening},number=>1);
            #$GEN->selContourize();
			$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
			$GEN->selectByFilter();
			if ( $GEN->getSelectCount() == 1 ) {
				$GEN->COM('sel_decompose',overlap=>'yes');
				#$GEN->selContourize();
				$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
			}
			else {
				$GEN->selClearFeature();
			}
            _deleteLayer(layer=>[$TmpLayer{tmp_layer}]);
            
            ####制作优化的大铜面到临时层 opt_big_copper
            #my $CoverageTol = 1;
            if ($item ne 'smd') {
                $Coverage_tmp = $Coverage_tmp + $CoverageTol_tmp/2;
                $CoverageTol_tmp = 0;     
            }
            #$Coverage = $CopperOpening < 0 ? -$Coverage : $Coverage;
            $GEN->workLayer(name=>$TmpLayer{big_copper_layer},number=>1);
            $GEN->selCopyOther(target_layer=>$TmpLayer{opt_big_copper},size=>$Coverage_tmp);
            $GEN->workLayer(name=>$TmpLayer{pad_touch_copper},number=>1);
            $GEN->selRefFeat(
                layers=>$TmpLayer{pad_opening},
                use=>'filter',
                mode=>'include'
            );
            if ($item eq 'bga') {
                $GEN->selectByFilter(attribute=>[{attribute=>'tl_spec_bga'}],operation=>'unselect');#non_plated,plated,via            
            }
            
            $GEN->selCopyOther(target_layer=>$TmpLayer{opt_big_copper},size=>2*$CopperOpening+$Coverage_tmp+$CoverageTol_tmp,invert=>'yes') if ( $GEN->getSelectCount() > 0 );
            $GEN->selRefFeat(
                layers=>$TmpLayer{pad_opening},
                use=>'filter',
                mode=>'cover'
            );
            if ($item eq 'bga') {
                $GEN->selectByFilter(attribute=>[{attribute=>'tl_spec_bga'}],operation=>'unselect');#non_plated,plated,via            
            }
            $GEN->selCopyOther(target_layer=>$TmpLayer{opt_big_copper},size=>2*$CopperOpening+$Coverage_tmp+$CoverageTol_tmp,invert=>'yes') if ( $GEN->getSelectCount() > 0 );
            if ($item eq 'bga') {
                $GEN->selectByFilter(attribute=>[{attribute=>'tl_spec_bga'}]);#non_plated,plated,via
                $GEN->selCopyOther(target_layer=>$TmpLayer{opt_big_copper},size=>2*$SpecBGACopperOpening+$Coverage_tmp+$CoverageTol_tmp,invert=>'yes') if ( $GEN->getSelectCount() > 0 );
            }
            $GEN->workLayer(name=>$TmpLayer{opt_big_copper},number=>1);
            #$GEN->selContourize();
            $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
            $GEN->selectByFilter();
            if ( $GEN->getSelectCount() == 1 ) {
                    $GEN->COM('sel_decompose',overlap=>'yes');
                    #$GEN->selContourize();
                    $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
            }
            else {
                    $GEN->selClearFeature();
            }
            $GEN->COM('sel_resize',size=>$Coverage_tmp+$CoverageTol_tmp,corner_ctl=>'no');


            ####制作准确的大铜面pad开窗到临时层 correct_sm_opening
            $GEN->workLayer(name=>$TmpLayer{pad_opening},number=>1);
            $GEN->selCopyOther(target_layer=>$TmpLayer{correct_sm_opening},size=>2);
            $GEN->workLayer(name=>$TmpLayer{opt_big_copper},number=>1);
            $GEN->selCopyOther(target_layer=>$TmpLayer{correct_sm_opening},invert=>'yes');
            $GEN->workLayer(name=>$TmpLayer{correct_sm_opening},number=>1);
            #$GEN->selContourize();
			$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
			$GEN->selectByFilter();
			if ( $GEN->getSelectCount() == 1 ) {
				$GEN->COM('sel_decompose',overlap=>'yes');
				#$GEN->selContourize();
				$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
			}
			else {
				$GEN->selClearFeature();
			}
            $GEN->selRefFeat(
                layers=>$TmpLayer{pad_touch_copper},
                use=>'filter',
                mode=>'disjoint'
            );
            $GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
			
            ####制作需要刮开的开窗部分
            $GEN->workLayer(name=>$TmpLayer{pad_opening},number=>1);
            $GEN->selCopyOther(target_layer=>$TmpLayer{sm_opening_free},size=>1);
            
            $GEN->workLayer(name=>$TmpLayer{correct_sm_opening},number=>1);
            $GEN->selCopyOther(target_layer=>$TmpLayer{sm_opening_free},invert=>'yes');
            
            $GEN->workLayer(name=>$tmp{$layer}.$BakSuffix,number=>1);
            $GEN->attributeReset();
            $GEN->COM('filter_reset',filter_name=>'popup');
            $GEN->selectByFilter(attribute=>[{attribute=>'.drill',option=>'via'}],polarity=>'negative');
            if ( $GEN->getSelectCount() > 0 ){
                    $GEN->selCopyOther(target_layer=>$TmpLayer{sm_opening_free});
            }
            $GEN->workLayer(name=>$TmpLayer{sm_opening_free},number=>1);
            #$GEN->selContourize();
			$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
			$GEN->selectByFilter();
			if ( $GEN->getSelectCount() == 1 ) {
				$GEN->COM('sel_decompose',overlap=>'yes');
				#$GEN->selContourize();
				$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
			}
			else {
				$GEN->selClearFeature();
			}
            $GEN->COM('sel_resize',size=>-0.05,corner_ctl=>'no');
            $GEN->selRefFeat(
                layers=>$TmpLayer{sm_opening},
                use=>'filter',
                mode=>'cover'
            );
            $GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
            $GEN->selRefFeat(
                layers=>$TmpLayer{sm_opening},
                use=>'filter',
                mode=>'disjoint'
            );
            $GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
            $GEN->selRefFeat(
                layers=>$TmpLayer{sm_opening},
                use=>'filter',
                mode=>'include'
            );
            $GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
			if ( $CopperOpening > 0 ) {
				$GEN->selRefFeat(
					layers=>$TmpLayer{pad_touch_copper},
					use=>'filter',
					mode=>'touch'
				);
				$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
			}
            $GEN->COM('sel_resize',size=>0.05,corner_ctl=>'no');
			
            #####去除小细丝
            $GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$tmp{$layer},dest_layer=>$TmpLayer{tmp_layer});
            
            $GEN->workLayer(name=>$TmpLayer{sm_opening_free},number=>1);
            $GEN->selCopyOther(target_layer=>$TmpLayer{tmp_layer},invert=>'yes');
            $GEN->workLayer(name=>$TmpLayer{tmp_layer},number=>1);
            #$GEN->selContourize();
            $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
            $GEN->selectByFilter();
            if ( $GEN->getSelectCount() == 1 ) {
                    $GEN->COM('sel_decompose',overlap=>'yes');
                    #$GEN->selContourize();
                    $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
            }
            else {
                    $GEN->selClearFeature();
            }
            $GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$TmpLayer{tmp_layer},dest_layer=>$TmpLayer{sliver_layer});
            #$GEN->COM('sel_resize',size=>-1,corner_ctl=>'no');
            #$GEN->COM('sel_resize',size=>1,corner_ctl=>'no');
            $GEN->selFill(min_brush=>2);
            $GEN->selContourize();
            $GEN->selCopyOther(target_layer=>$TmpLayer{sliver_layer},invert=>'yes',size=>0.05);
            $GEN->workLayer(name=>$TmpLayer{sliver_layer},number=>1);
            #$GEN->selContourize();
			$GEN->COM('sel_cont_resize',accuracy=>0,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
                        $GEN->COM('sel_resize',size=>-0.05,corner_ctl=>'no');
                        $GEN->COM('sel_resize',size=>0.05,corner_ctl=>'no');
                        $GEN->selectByFilter();
			if ( $GEN->getSelectCount() == 1 ) {
				$GEN->COM('sel_decompose',overlap=>'yes');
				#$GEN->selContourize();
				$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
			}
			else {
				$GEN->selClearFeature();
			}
            $GEN->selectByFilter(polarity=>'positive');
            if ( $GEN->getSelectCount() > 0 ) {
                $GEN->selCopyOther(target_layer=>$TmpLayer{sm_opening_free},size=>0.05);
                $GEN->workLayer(name=>$TmpLayer{sm_opening_free},number=>1);
                #$GEN->selContourize();
                $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
                $GEN->selectByFilter();
                if ( $GEN->getSelectCount() == 1 ) {
                        $GEN->COM('sel_decompose',overlap=>'yes');
                        #$GEN->selContourize();
                        $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
                }
                else {
                        $GEN->selClearFeature();
                }
            }
            $GEN->selClearFeature();

            ##去除小面积物件
            if ($DeleteSamllArea eq 'Yes') {
                $GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$tmp{$layer},dest_layer=>$TmpLayer{tmp_layer});
                $GEN->workLayer(name=>$TmpLayer{sm_opening_free},number=>1);
                $GEN->selCopyOther(target_layer=>$TmpLayer{tmp_layer},invert=>'yes');
                $GEN->workLayer(name=>$TmpLayer{tmp_layer},number=>1);
                #$GEN->selContourize();
                $GEN->COM('sel_cont_resize',accuracy=>0,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
                $GEN->selectByFilter();
                if ( $GEN->getSelectCount() == 1 ) {
                        $GEN->COM('sel_decompose',overlap=>'yes');
                        #$GEN->selContourize();
                        $GEN->COM('sel_cont_resize',accuracy=>0,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
                }
                else {
                        $GEN->selClearFeature();
                }
                $GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$TmpLayer{tmp_layer},dest_layer=>$TmpLayer{samll_area_layer});
                $GEN->workLayer(name=>$TmpLayer{tmp_layer},number=>1);
                $GEN->selectByFilter(polarity=>'positive');
                $GEN->COM("sel_clean_surface,accuracy=0,clean_size=$SmallAreaOpen,clean_mode=area,max_fold_len=0");
                $GEN->workLayer(name=>$TmpLayer{samll_area_layer},number=>1);
                $GEN->selRefFeat(
                        layers=>$TmpLayer{tmp_layer},
                        use=>'filter',
                        mode=>'touch'
                );
                $GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
                $GEN->selectByFilter(polarity=>'positive');
                if ( $GEN->getSelectCount() > 0 ) {
                    $GEN->selCopyOther(target_layer=>$TmpLayer{sm_opening_free},size=>0.05);
                    $GEN->workLayer(name=>$TmpLayer{sm_opening_free},number=>1);
                    #$GEN->selContourize();
                    $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
                    $GEN->selectByFilter();
                    if ( $GEN->getSelectCount() == 1 ) {
                            $GEN->COM('sel_decompose',overlap=>'yes');
                            #$GEN->selContourize();
                            $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
                    }
                    else {
                            $GEN->selClearFeature();
                    }
                }
                $GEN->selClearFeature();
            }


			
            ###add smdefpad_sm_totally and smdefpad_sm_partly
            _deleteLayer(layer=>[$TmpLayer{tmp_layer}]);
            if ( $GEN->isLayerExists(job=>$Job,layer=>$TmpLayer{pad_on_copper_gasket}) ) {
                    $GEN->workLayer(name=>$TmpLayer{pad_touch_copper},number=>1);
                    $GEN->selRefFeat(
                            layers=>$TmpLayer{pad_on_copper_gasket},
                            use=>'filter',
                            mode=>'touch'
                    );
                    if ( $GEN->getSelectCount() > 0 ) {
                            $GEN->selCopyOther(target_layer=>$TmpLayer{tmp_layer});
                            $GEN->workLayer(name=>$tmp{$layer},number=>1);
                            $GEN->selRefFeat(
                                    layers=>$TmpLayer{tmp_layer},
                                    use=>'filter',
                                    mode=>'include'
                            );
                            if ( $GEN->getSelectCount() > 0 ) {
                                    $GEN->selAddAttr(attribute=>'smdefpad_sm_totally');
                            }
                    }
            }
            $GEN->workLayer(name=>$tmp{$layer},number=>1);
            $GEN->selRefFeat(
                    layers=>$TmpLayer{sm_opening_free},
                    use=>'filter',
                    mode=>'touch'
            );
            $GEN->selectByFilter(
                    attribute=>'smdefpad_sm',
                    operation=>'unselect'
            );
            $GEN->selectByFilter(
                    attribute=>'smdefpad_sm_totally',
                    operation=>'unselect'
            );
            if ( $GEN->getSelectCount() > 0 ) {
                    $GEN->selAddAttr(attribute=>'smdefpad_sm_partly');
            }
            _deleteLayer(layer=>[$TmpLayer{tmp_layer}]);
            
            ###copy to sm layer
            $GEN->workLayer(name=>$TmpLayer{sm_opening_free},number=>1);
            $GEN->COM('sel_delete_atr',attributes=>'smdefpad_sm');
            #$GEN->selContourize();
            $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
            $GEN->selectByFilter();
            if ( $GEN->getSelectCount() == 1 ) {
                    $GEN->COM('sel_decompose',overlap=>'yes');
                    #$GEN->selContourize();
                    $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
            }
            else {
                    $GEN->selClearFeature();
            }
            $GEN->selAddAttr(attribute=>[{attribute=>'.string',text=>'sm_defined_pad_shave'}]);
            ###去掉有shave碰到开窗上是surface的部分
            $GEN->workLayer(name=>$TmpLayer{sm_opening_free},number=>1);
            $GEN->selRefFeat(
                layers=>$tmp{$layer},
                use=>'filter',
                mode=>'touch',
                f_types=>'surface'
            );
            $GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
            $GEN->selCopyOther(target_layer=>$TmpLayer{sm_defined_tmp_layer},invert=>'yes');
            $GEN->selCopyOther(target_layer=>$sm_tmp_bk,invert=>'yes');
            
            $GEN->selCopyOther(target_layer=>$ref_layer);
        }

        if($GEN->isLayerExists(job=>$Job,layer=>$TmpLayer{sm_defined_tmp_layer})){
            $GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$TmpLayer{sm_defined_tmp_layer},dest_layer=>$tmp{$layer},mode=>'append',invert=>'no');
        }
        
        $GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$sm_tmp_bk,dest_layer=>$tmp{$layer});

        $GEN->COM("disp_on");

        _deleteLayer(layer=>[$sm_tmp_bk,$TmpLayer{sm_defined_tmp_layer}]);
        
        
		###补偿用户定义的属性将忽略处理的开窗
		$GEN->workLayer(name=>$tmp{$layer},number=>1);
		if ( $PAR->{ignore_attr_comp} and $PAR->{ignore_attr_comp} eq 'Yes' and $IgnoreAttr ) {
			$GEN->workLayer(name=>$tmp{$layer},number=>1);
			$GEN->selectByFilter(attribute=>$IgnoreAttr);
			if ( $GEN->getSelectCount() > 0 ) {
				$GEN->COM('sel_resize',size=>$CopperOpening*2,corner_ctl=>'no');
			}
		}

		##恢复via 
		$GEN->workLayer(name=>$tmp{$layer}.$BakSuffix,number=>1);
		$GEN->attributeReset();
		$GEN->COM('filter_reset',filter_name=>'popup');
		$GEN->selectByFilter(attribute=>[{attribute=>'.drill',option=>'via'}],polarity=>'positive');
		if ( $GEN->getSelectCount() > 0 ){
			$GEN->selCopyOther(target_layer=>$tmp{$layer});
            $GEN->selCopyOther(target_layer=>$sm_tmp_bk);
		}
#               # 恢复负片层
#                my $negative_open_lyr = $tmp{$layer}.'_negative_open_lyr_tl_script';
#                $GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$tmp{$layer}.$BakSuffix,dest_layer=>$negative_open_lyr);
#                $GEN->workLayer(name=>$negative_open_lyr,number=>1);
#                $GEN->attributeReset();
#		$GEN->COM('filter_reset',filter_name=>'popup');
#                $GEN->selectByFilter(polarity=>'positive');
#                if ( $GEN->getSelectCount() > 0 ){
#                    $GEN->selectByFilter(polarity=>'positive');
#                    $GEN->COM('sel_resize',size=>'-1',corner_ctl=>'no');
#                }
#                $GEN->attributeReset();
#		$GEN->COM('filter_reset',filter_name=>'popup');
#                $GEN->selectByFilter(polarity=>'negative');
#                $GEN->COM('sel_resize',size=>1,corner_ctl=>'no') if ( $GEN->getSelectCount() > 0 );
#                $GEN->selContourize();
#                
#                $GEN->workLayer(name=>$tmp{$layer}.$BakSuffix,number=>1);
#                $GEN->selRefFeat(
#                    layers=>$negative_open_lyr,
#                    use=>'filter',
#                    mode=>'disjoint',
#                    filter=>{
#                        filter_name => 'popup',
#                        polarity=>'negative',
#                    }
#                );
#		if ( $GEN->getSelectCount() > 0 ){
#			$GEN->selCopyOther(target_layer=>$tmp{$layer},size=>0);
#		}
                #_deleteLayer(layer=>[$negative_open_lyr]);

                
                
		$GEN->workLayer(name=>$tmp{$layer},number=>1);
    }
    
	###output and return status, if genesis error, it will output genesis error command
	unless ($GEN->{STATUS}){
                $GEN->COM("disp_on");
		return $Return;
	}
	else{
        $GEN->COM("disp_on");
		$GUI->msgbox(-icon=>'error',-text=>join("\n",@{$GEN->{STATUS}}));
		#addFlowNotes(-notes=>"   Genesis Error:\n   ".join("\n   ",@{$GEN->{STATUS}}));
		return 'Error';
	}
}
catch Error::Simple with {
        $GEN->COM("disp_on");
	my $error = encode("utf8",shift);
	$GUI->msgbox(-icon=>'error',-text=>$error);
	return 'Error';
}
finally{
	$GEN->COM("disp_on");
	_deleteLayer(layer=>[values %TmpLayer]);
};

sub _deleteLayer{
    my %par = @_;
    foreach my $layer(@{$par{layer}}){
        $GEN->deleteLayer(layer=>$layer) if ($GEN->isLayerExists(job=>$Job,layer=>$layer));
    }
}

sub select_work_layer{
	my %par = @_;
	##获取工作层
    my @sm;
	my %matrix = $GEN->getMatrix(job=>$Job,type=>'hash');
	foreach my $layer (sort {$matrix{$a}{row} <=> $matrix{$b}{row}}  keys %matrix) {
		if(defined($matrix{$layer}{context}) and $matrix{$layer}{context} eq 'board' ){
			if (defined($matrix{$layer}{tl_type}) and $matrix{$layer}{tl_type} eq 'solder_mask') {
				push @sm,$layer;
			}
		}
	}
	##
	unless( @sm ){
		$GUI->msgbox(-icon=>'warning',-text=>'资料中无防焊层,请确认');
		return 'Cancel';
	}
	##
	if ($PAR->{is_select_lyr} eq 'Yes' and scalar(@sm) > 1) {
		my (%tmp_matrix);
		foreach my $layer (@sm) {
			$tmp_matrix{$layer} = $matrix{$layer};
		}
		@sm = $GUI->select_layer(
			-title=>'请选择工作层别',
			-layermatrix=>\%tmp_matrix,
			-default => [keys %tmp_matrix],
			-selectmode => 'multiple');#single
		return 'Cancel' unless(@sm);
	}
	return \@sm;
}