diff --git a/README.md b/README.md index 29db040..bf617ad 100644 --- a/README.md +++ b/README.md @@ -1,2 +1 @@ -# new_file - +# 化整为零思维与文件存储仿真 diff --git a/TK_ui.py b/TK_ui.py new file mode 100644 index 0000000..0ba8fc4 --- /dev/null +++ b/TK_ui.py @@ -0,0 +1,1308 @@ +# -*- encoding: utf-8 -*- +""" +@File : test2.py +@License : (C)Copyright 2018-2022 + +@Modify Time @Author @Version @Description +------------ ------- -------- ----------- +2023/8/21 13:45 zart20 1.0 None +""" + +import re +import tkinter as tk +from tkinter import scrolledtext +from math import sin, cos, pi +import numpy as np +from PIL import Image, ImageTk + +import read_bin +from files_sys_sim import * + +file_name_set = set() # 文件项的唯一集合 +blocks_label_set = set() # 文件标签的唯一集合 + + +def find_missing_and_duplicates(lst): + print("列表长度:", len(lst)) + expected_set = set(range(1, 100)) + input_set = set(lst) + print("转换集合长度:", len(input_set)) + + missing_numbers = list(expected_set - input_set) + duplicate_numbers = list(input_set.intersection(expected_set)) + + print("缺失的数字:", missing_numbers) + print("重复的数字:", duplicate_numbers) + + return missing_numbers, duplicate_numbers + + +def get_unique_tag(): # 获取唯一字母标签 + for ascii_code in range(65, 91): + character = chr(ascii_code) + if character not in blocks_label_set: + blocks_label_set.add(character) + return character + + +def set_canvas_size(foreground_image, up_or_down=None): + # 调整前景 + new_width = 555 # 新的宽度 + if up_or_down == "up": + new_height = 245 # 新的高度 + else: + new_height = 555 # 新的高度 + foreground_image = foreground_image.resize((new_width, new_height), Image.LANCZOS) + foreground_photo = ImageTk.PhotoImage(foreground_image) + return foreground_photo + + +class InterfaceFile: + def __init__(self, root: tk.Tk): + self.current_step = None + self.file_modi_tag = False # 文件修改状态 + self.massages = [] # 系统消息队列 + self.sim_fat_copy = None # 仿真FAT表复制临时列表,用于校验 + self.sim_file_copy = None # 仿真文件复制临时列表,用于校验 + self.ex_disk_oc = True # 交替显示保存占用和添加占用标志 + self.ex_disk_la = True # 修改保存标签和清除标签的标志 + self.sim_disk_copy = None # 磁盘复制临时列表,用于校验 + self.block_modi_tag = False # 磁盘块修改标志置否 + self.block_modi_lb = None # 磁盘块标签值初始化 + self.old_key = None # FAT表上一次的记录值 + self.fat_modi_num = None # 打开下一个FAT单元格之前的修改数值 + self.fat_modi_tag = False # 修改状态标签,为True时进入修改状态 + self.clear_tag = True # 清除标签,让标签清理和fat清理操作互斥 + self.check = None # 检查磁盘条件 + self.code = None # 当前磁盘块标签字母 + self.creating = True # 正在创建的状态 + self.SimFAT = initialize_simfat() # SimFAT 表初始化 + self.SimDisk = initialize_simdisk() # SimDisk 区域初始 + self.FolderItems = [] # 文件项储存 + self.fat_unique_set = {0} # fat表去重集合,防止在一个位置建立多个磁盘块 + self.root = root + self.canvas_width = 1440 + self.canvas_height = 830 + # self.root.geometry(f'{self.canvas_width}x{self.canvas_height}+{2100}+{100}') + self.root.geometry(f'{self.canvas_width}x{self.canvas_height}') + self.root.title("文件系统仿真TK版") + + self.canvas = tk.Canvas(root, width=self.canvas_width, height=self.canvas_height, bg="white") + self.canvas.pack(fill="both", expand=True) + + self.fat_table_position_mapping = dict() # FAT表位置-序号映射字典 + self.blocks_position_mapping = dict() # 磁盘块位置-序号映射字典 + + # 创建菜单栏 + menubar = tk.Menu(self.root, font=("son", 16)) + self.root.config(menu=menubar) + + # 创建文件菜单 + file_menu = tk.Menu(menubar, tearoff=0) + file_menu.configure(font=("son", 16)) + menubar.add_cascade(label="真实磁盘操作", menu=file_menu) + + # 在文件菜单中添加选项 + sector_0 = read_bin.read_sector_0() + file_menu.add_command(label="读取磁盘文件0扇区", command=lambda: self.show_real_disk("磁盘0扇区", sector_0)) + sector_FAT1_1 = read_bin.read_sector_FAT1() + file_menu.add_command(label="读取磁盘文件FAT1", + command=lambda: self.show_real_disk("FAT1_0扇区", sector_FAT1_1)) + root_path0 = read_bin.read_sector_root_path(0) + file_menu.add_command(label="读取根目录0扇区", + command=lambda: self.show_real_disk("根目录0扇区", root_path0)) + root_path1 = read_bin.read_sector_root_path(1) + file_menu.add_command(label="读取根目录1扇区", + command=lambda: self.show_real_disk("根目录1扇区", root_path1)) + + # 创建保存菜单 + save_menu = tk.Menu(menubar, tearoff=0) + save_menu.configure(font=("son", 16)) + menubar.add_cascade(label="手动保存", menu=save_menu) + save_menu.add_command(label="开启手动保存模式", command=lambda : self.manual_save()) + + # 将鼠标左键点击事件绑定到函数on_left_click + self.canvas.bind("", self.on_left_click) + + background_image = Image.open("img/bg2.png") + background_image = background_image.resize((1440, 830)) + background_photo = ImageTk.PhotoImage(background_image) + + # 在Canvas上显示背景图片 + self.canvas.create_image(0, 0, anchor="nw", image=background_photo) + + # 载入前景图片 + foreground_image_pink = Image.open("img/pink_bg.png") + foreground_photo_pink = set_canvas_size(foreground_image_pink, "up") + foreground_image_purple = Image.open("img/purple_bg.png") + foreground_photo_purple = set_canvas_size(foreground_image_purple, "up") + foreground_image_jb = Image.open("img/jade_blue_bg.png") + foreground_photo_jb = set_canvas_size(foreground_image_jb) + foreground_image_sky_blue = Image.open("img/sky_blue_bg.png") + foreground_photo_sky_blue = set_canvas_size(foreground_image_sky_blue) + + x1, y1, x2, y2 = 1130, 10, 1433, 819 + self.canvas_child = tk.Canvas(self.canvas,) + self.canvas_child.place(x=x1,y=y1) + self.canvas_child.config(width=303, height=809) + self.canvas_child.create_rectangle(x1, y1, x2, y2, outline="white", fill="white") + + # 在Canvas上显示调整后大小的前景图片 + self.canvas.create_image(10, 10, anchor="nw", image=foreground_photo_pink) + self.canvas.create_image(570, 10, anchor="nw", image=foreground_photo_purple) + self.canvas.create_image(10, 265, anchor="nw", image=foreground_photo_jb) + self.canvas.create_image(570, 265, anchor="nw", image=foreground_photo_sky_blue) + + # 保留图片引用以防止垃圾回收 + self.canvas.background_image = background_photo + self.canvas.foreground_image_pink = foreground_photo_pink + self.canvas.foreground_photo_purple = foreground_photo_purple + self.canvas.foreground_photo_jb = foreground_photo_jb + self.canvas.foreground_photo_sky_blue = foreground_photo_sky_blue + + # 按键布局 + image_create = Image.open("img/创建文件.png") + self.photo_create = ImageTk.PhotoImage(image_create) + self.set_canvas_button([348, 20], self.photo_create, self.creat_file, bg="#996BC7") + + image_save = Image.open("img/保存.png") + self.photo_save = ImageTk.PhotoImage(image_save) + self.file_save_button = self.set_canvas_button([435, 20], self.photo_save, self.save_file, bg="#996BC7") + + image_query = Image.open("img/查询.png") + self.photo_query = ImageTk.PhotoImage(image_query) + self.set_canvas_button([495, 20], self.photo_query, self.query_file, bg="#996BC7") + + image_create_path = Image.open("img/创建目录项.png") + self.photo_create_path = ImageTk.PhotoImage(image_create_path) + self.creat_path_button = self.set_canvas_button([825, 20], self.photo_create_path, self.creat_path, bg="#785FDA") + + image_clear_file = Image.open("img/清除目录项.png") + self.photo_clear_file = ImageTk.PhotoImage(image_clear_file) + self.clear_file_button = self.set_canvas_button([915, 20], self.photo_clear_file, self.clear_file_label, bg="#785FDA") + + image_check = Image.open("img/文件校验.png") + self.photo_check = ImageTk.PhotoImage(image_check) + self.file_check_button = self.set_canvas_button([1015,20], self.photo_check, self.file_check) + + image_reset = Image.open("img/重置.png") + self.photo_reset = ImageTk.PhotoImage(image_reset) + self.set_canvas_button([1065, 20], self.photo_reset, self.restart, bg="#785FDA") + + image_fat_check = Image.open("img/校验.png") + self.photo_fat_check = ImageTk.PhotoImage(image_fat_check) + self.fat_check_button = self.set_canvas_button([165, 274], self.photo_fat_check, self.fat_checkout) + + image_clear_form = Image.open("img/清除表单项.png") + self.photo_clear_form = ImageTk.PhotoImage(image_clear_form) + self.set_canvas_button([270, 274], self.photo_clear_form, self.clear_fat_label) + + image_save_form = Image.open("img/保存表单项.png") + self.photo_save_form = ImageTk.PhotoImage(image_save_form) + self.set_canvas_button([368, 274], self.photo_save_form, self.modi_fat_save) + + image_change_form = Image.open("img/修改表单项.png") + self.photo_change_form = ImageTk.PhotoImage(image_change_form) + self.set_canvas_button([465, 274], self.photo_change_form, self.modi_fat) + + image_disk_check = Image.open("img/校验2.png") + self.photo_disk_check = ImageTk.PhotoImage(image_disk_check) + self.disk_check_button = self.set_canvas_button([680, 274], self.photo_disk_check, self.disk_checkout) + + image_save_occupy = Image.open("img/保存占用.png") + self.photo_save_occupy = ImageTk.PhotoImage(image_save_occupy) + image_add_occupy = Image.open("img/添加占用.png") + self.photo_add_occupy = ImageTk.PhotoImage(image_add_occupy) + self.exchange_button_disk_occupy() # 动态按钮函数用于 表示交保存和添加占用 + + image_revamp_label = Image.open("img/修改标签.png") + self.photo_revamp_label = ImageTk.PhotoImage(image_revamp_label) + image_save_label = Image.open("img/保存标签.png") + self.photo_save_label = ImageTk.PhotoImage(image_save_label) + self.exchange_button_disk_label() # 动态标签函数用于 表示交换修改和保存标签 + + image_clear_label = Image.open("img/清除标签.png") + self.photo_clear_label = ImageTk.PhotoImage(image_clear_label) + self.set_canvas_button([1040, 274], self.photo_clear_label, self.clear_disk_label) + + # 设置 + self.file_name_label = self.set_canvas_label_entry([20, 21], "输入文件名", 10, [120, 20]) # 设置输入框和输入标签 + self.blocks_num_label = self.set_canvas_label_entry([255, 21], "块数", 3, [295, 20]) # 设置输入框和输入标签 + self.path_name_label = self.set_canvas_label_entry([580, 21], "文件夹(目录)", 10, [690, 20]) # 设置输入框和输入标签 + + # 设置canvas_label + self.canvas.create_text(20, 275, text="文件分配表FAT", anchor="nw", fill="white", font=("Arial", 14)) + self.canvas.create_text(20, 65, text="初始文件模拟区:", anchor="nw", fill="white", font=("Arial", 14)) + self.canvas.create_text(580, 275, text="磁盘模块", anchor="nw", fill="white", font=("Arial", 14)) + self.canvas.create_text(575, 70, anchor=tk.NW, text="文件名\t首块\t块数\t标签", font=("Arial", 14), + fill="white", ) + self.canvas_child.create_text(150, 21, text="操作指引", anchor=tk.CENTER, fill="black", font=("son", 14, "bold")) + self.canvas_child.create_text(150, 240, text="系统消息", anchor=tk.CENTER, fill="black", font=("son", 14, "bold")) + + self.photo_fk3 = self.image_transition("img/fk3.png") # 黄色方块,创建文件用 + self.photo_fk1 = self.image_transition("img/fk1.png") # 透明位置方块 提供棋盘 + self.photo_fk2 = self.image_transition("img/fk2.png") # 灰色方块,代表未选择方块,或者占用方块 + + # FAT模块 + self.draw_fat_line() + + # 磁盘模块 + self.draw_disk_background() + + # 创建滚动文本框 + self.info_text = scrolledtext.ScrolledText(self.canvas_child, wrap=tk.WORD, width=25, height=24) + self.info_text.place(x=10,y=265) + self.info_text.config(font=("Arial", 14)) + + self.canvas_child.bind("", self.info_xy) + + def info_xy(self,event): + print(event.x,event.y) + + def sys_info(self, massage): + '''系统消息''' + self.info_text.insert("end", massage+"\n") + self.info_text.see("end") + + def special_info(self, s_msg): + '''操作指引消息''' + self.canvas_child.delete("s_msg") + s_msgs = s_msg.split("\n") + for i, msg in enumerate(s_msgs): + self.canvas_child.create_text(150,60+i*25,text=msg,font=("Arial", 14), anchor=tk.CENTER, tags="s_msg") + + + def exchange_button_disk_label(self): + if self.ex_disk_la: + self.set_canvas_button([950, 274], self.photo_revamp_label, self.modi_block_lb, tags="prl") + else: + self.set_canvas_button([950, 274], self.photo_save_label, self.modi_block_save, tags="psl") + + def exchange_button_disk_occupy(self): + if self.ex_disk_oc: + self.add_occupy_button = self.set_canvas_button([860, 274], self.photo_add_occupy, self.add_occupy, tags="pao") + else: + self.set_canvas_button([860, 274], self.photo_save_occupy, self.save_occupy, tags="pso") + + def set_canvas_label_entry(self, label_pot: list, label_text: str, entry_width: int, entry_pot: list): + self.canvas.create_text(label_pot[0], label_pot[1], text=label_text, anchor="nw", fill="white", + font=("Arial", 14)) + return self.set_canvas_entry(entry_pot[0], entry_pot[1], entry_width, "") + + def set_canvas_button(self, button_pot: list, button_photo: ImageTk.PhotoImage, command, tags=None, bg="#3E97C1"): + button = tk.Button(self.canvas, image=button_photo, command=command, bd=0, relief="raised", + highlightthickness=0, compound="center", bg=bg, activebackground=bg) + self.canvas.create_window(button_pot, anchor="nw", window=button, tags=tags) + return button + + def set_canvas_entry(self, x, y, entry_width: int, default: str, tags=None, font_size=None): + if not font_size: + font_size = 16 + entry_file_name = tk.Entry(self.root, width=entry_width, ) + entry_file_name.configure(font=("Arial", font_size), borderwidth=1, relief="sunken", ) + entry_file_name.insert(0, default) + self.canvas.create_window(x, y, anchor="nw", window=entry_file_name, tags=tags) + return entry_file_name + + def show_fat(self, row, column, length_side=430): + """映射显示FAT表""" + tags = "fat_tag" # 定义删除标志 + side_half = length_side // 20 # 每行和每列的间隔距离的一半 + num = self.SimFAT[row][column] + if num != 0: + x = self.fat_table_position_mapping[row, column][0] + side_half + y = self.fat_table_position_mapping[row, column][1] + side_half + self.canvas.create_text(x, y, anchor=tk.CENTER, text=num, font=("Arial", 16), + fill="white", tags=tags) + + def show_all_fat(self): + self.canvas.delete("fat_tag") + for i in range(10): + for n in range(10): + self.show_fat(i, n) + + def load_files_list(self, fat_ls: list[int], block_label="default"): # 直接根据含第一块位置的fat表生成fat和disk显示 + # 假设block的去重在数据层面就已经处理好了 + self.show_all_disk() # 更新磁盘显示 + for i, value in enumerate(fat_ls): + row = value // 10 + column = value % 10 + if block_label == "default": + block_label = self.SimDisk[row][column][0] + if i < len(fat_ls) - 1: + self.SimFAT[row][column] = fat_ls[i + 1] + else: + self.SimFAT[row][column] = "FF" + self.SimDisk[row][column] = f"{block_label}{i + 1}" + self.show_disk(row, column, True) # 最后创建颜色才为黄色 + self.show_all_fat() # 更新fat表显示 + + def draw_fat_line(self, left_top_point=(80, 365), length_side=430): + """FAT框架显示""" + left_x, left_y = left_top_point # 偏移量x和y + short_side = length_side // 10 # 每行和每列的间隔距离 + + for i in range(10): # 坐标映射 + for n in range(10): + x = short_side * i + left_x + y = short_side * n + left_y + self.fat_table_position_mapping[n, i] = [x, y] + + for line in range(11): # 画线 + x1, x2 = short_side * line + left_x, left_x + y1, y2 = short_side * line + left_y, left_y + self.canvas.create_line(x1, left_y, x1, left_y + length_side, fill="white", width=1) + self.canvas.create_line(left_x, y1, left_x + length_side, y1, fill="white", width=1) + + for num in range(10): # 画序号 + x, y = short_side * num + left_x + (short_side // 2), short_side * num + left_y + (short_side // 2) + self.canvas.create_text(x, left_y - 20, text=f"{num}", font=("Arial", 12), anchor="center", fill="white") + self.canvas.create_text(left_x - 20, y, text=f"{num}", font=("Arial", 12), anchor="center", fill="white") + + return self.fat_table_position_mapping + + def show_disk(self, row, column, color_tag=None): + """映射显示单个磁盘块""" + tags = "fat_disk" # 定义删除标志 + text = self.SimDisk[row][column] + if text != 0: + x = self.blocks_position_mapping[row, column][0] + 1 + y = self.blocks_position_mapping[row, column][1] + 1 + if color_tag: + self.draw_blocks(x, y, tags, text, "label_disk", self.photo_fk3) + else: + self.draw_blocks(x, y, tags, text, "label_disk", self.photo_fk2) + + def show_all_disk(self): + """显示所有磁盘块""" + self.canvas.delete("fat_disk") + self.canvas.delete("label_disk") + for i in range(10): + for n in range(10): + self.show_disk(i, n) + + def draw_disk_background(self, left_top_point=(650, 365), length_side=430): + """创建磁盘块图例,并返回每个磁盘块的磁盘块的序号位置映射关系""" + left_x, left_y = left_top_point # 偏移量x和y + short_side = length_side // 10 # 每行和每列的间隔距离 + + for i in range(10): + for n in range(10): + x, y = short_side * i + left_x, short_side * n + left_y + self.canvas.create_image(x, y, anchor=tk.NW, image=self.photo_fk1) + self.blocks_position_mapping[n, i] = [x, y] # 保存每个磁盘块的序号位置映射关系 + + for num in range(10): + i = num + x1, x2 = short_side * i + left_x + (short_side // 2), left_x - 20 + y = short_side * i + left_y + (short_side // 2) + self.canvas.create_text(x1, left_y - 20, text=f"{num}", font=("Arial", 12), anchor="center", fill="white") + self.canvas.create_text(x2, y, text=f"{num}", font=("Arial", 12), anchor="center", fill="white") + + return self.blocks_position_mapping + + def modify_image_color(self, image, channel_offset): # 调整方块颜色 + image_array = np.array(image) # 将图像转换为NumPy数组 + modified_image_array = image_array + np.array(channel_offset) # 对每个通道进行加减操作(包括Alpha通道) + modified_image_array = np.clip(modified_image_array, 0, 255) # 限制像素值在0到255之间 + modified_image = Image.fromarray(np.uint8(modified_image_array)) # 创建新的图像 + return modified_image + + def image_transition(self, file_path, side=43, channel_offset=(0, 0, 0, 0)): + """修改图片大小和颜色""" + image = Image.open(file_path) + if sum(channel_offset) != 0: + image = self.modify_image_color(image, channel_offset) # 按RGBA调整颜色 + image.thumbnail((side, side)) + return ImageTk.PhotoImage(image) + + def query_file(self): + '''查询功能''' + # self.sys_info("临时消息") + file_name = self.file_name_label.get() + if file_name in file_name_set: + for item in self.FolderItems: + if file_name == item[0]: + file_label = initialize_fileblock(item[2], item[3]) + self.canvas.delete("fk3") + self.creat_file_blocks(file_label) + self.blocks_num_label.delete(0, tk.END) + block_nums = read_sim_fat(int(item[1]), self.SimFAT) # 通过首块fat获取全部文件fat + self.load_files_list(block_nums) + self.sys_info(f"查询成功!") + else: + print("文件夹中无该文件!") + self.sys_info("文件夹中无该文件!") + + def check_condition(self, file_name, start_block_num, block_num): # 检查创建和保存条件 + + for row in self.SimFAT: # 更新唯一SimFAT表 + self.fat_unique_set.update(row) + if 'FF' in self.fat_unique_set: # 判断磁盘空间时,排除掉非位置字符 + self.fat_unique_set.remove('FF') + self.fat_unique_set.remove(100) # 收藏判断需要删除100这个非位置值 + + if self.clear_tag: + if file_name != "" and block_num != "": # 文件名和块数不为空才能保存 + if block_num.isdigit(): # 填入块数为正整数才能保存 + if file_name not in file_name_set: # 文件名不重复才能保存 + if len(self.fat_unique_set) + int(block_num) <= 100: + if start_block_num: + if int(start_block_num) not in self.fat_unique_set: + # fat_arr = self.generate_fat_array(start_block_num, int(block_num), self.SimFAT) # 生成fat表 + # if fat_arr: # 有返回才进行显示 + return True + else: + self.sys_info("首块位置已被占用!") + else: + self.sys_info("磁盘已满!") + else: + self.sys_info("磁盘空间不足!") + else: + self.sys_info("文件名不能重复!") + else: + self.sys_info("请输入正整数!") + else: + self.sys_info("文件名或块数不能为空!") + else: + if self.fat_modi_tag: + self.sys_info("正在执行FAT表修改任务!\n请完成FAT校验后再进行操作!") + elif self.block_modi_tag: + self.sys_info("正在执行磁盘块修改任务!\n请完成磁盘块校验后再进行操作!") + + def creat_file(self, file_name=None, f_block=None, block_num=None): + print("创建文件") + if not file_name: + file_name = self.file_name_label.get() + if not block_num: + block_num = self.blocks_num_label.get() + if not f_block: + f_block = self.select_fat_unique() + + self.check = self.check_condition(file_name, f_block, block_num) # 执行数据合规检查 + + if self.check: # 合规时执行 + if self.creating: # 初始时获取字母, + self.code = get_unique_tag() + self.creating = False # 获取后除非触发保存,下次创建不更新字母 + file_label = initialize_fileblock(block_num, self.code) + self.canvas.delete("fk3") # 新创建文件前执行一次删除 + self.creat_file_blocks(file_label) + self.sys_info("创建文件成功!") + + def creat_file_start_end_label(self, i, n, left_x, left_y, side, tags): # 创建起始和尾部标签组件 + if i == 0: + self.canvas.create_text(left_x, left_y - 50, anchor=tk.NW, text="起始", font=("Arial", 14), fill="white", + tags=tags) + offset = 15 # 箭头外扩端点偏移量 + end_x = left_x + side - n * side * 0.3 # x轴线段从右到左节结束点x值 + self.canvas.create_line(left_x + side, left_y - offset, end_x, left_y - offset, fill="white", tags=tags) + arrow_angle = 30 # 箭头的夹角 + angle_rad = arrow_angle * (pi / 180) # 计算幅度 + self.canvas.create_line(end_x, left_y - offset, end_x + 10 * cos(angle_rad), + left_y - offset + 10 * sin(angle_rad), fill="white", tags=tags) + self.canvas.create_line(end_x, left_y - offset, end_x + 10 * cos(-angle_rad), + left_y - offset + 10 * sin(-angle_rad), fill="white", tags=tags) + if i == n - 1: + self.canvas.create_text(left_x - i * side, left_y - 30, anchor=tk.NW, text="尾部", font=("Arial", 14), + fill="white", tags=tags) + + def draw_blocks(self, x, y, tags, label_block, label_ctrl=None, image=None): # 画创建文件中的方块和文字 + if not image: + image = self.photo_fk3 + self.canvas.create_image(x, y, anchor=tk.NW, + image=image, tags=tags) + if label_ctrl: + tags = label_ctrl + self.canvas.create_text(x + 5, y + 12, anchor=tk.NW, + text=label_block, font=("Arial", 12), tags=tags) + + def creat_file_blocks(self, list: list): + left_x = 465 + left_y = 150 + side = 43 # 元素边 + tags = "fk3" + n = len(list) + if n <= 11: + for i in range(n): + x = left_x - i * side + y = left_y + self.draw_blocks(x, y, tags, f"{list[i]}") + self.creat_file_start_end_label(i, n, left_x, left_y, side, tags) + else: + end_i = n - 5 # 取最后5块 + for i in range(n): + x = left_x - i * side + y = left_y + self.creat_file_start_end_label(i, 11, left_x, left_y, side, tags) + if i < 5: + self.draw_blocks(x, y, tags, f"{list[i]}") + elif i == 5: + self.draw_blocks(x, y, tags, "...") + elif i < 11: + self.draw_blocks(x, y, tags, f"{list[end_i]}") + end_i += 1 + + def creat_path(self): + print("创建目录项") + if self.clear_tag: + path_name = self.path_name_label.get() # 获取文件夹 + text_ls = path_name.split(",") + if text_ls[0] not in file_name_set: + if len(text_ls) == 3 and text_ls[1].isdigit() and text_ls[2].isdigit(): # 确保格式和类型一致 + if self.check_condition(text_ls[0], text_ls[1], text_ls[2]): + self.save_file(text_ls[0], text_ls[1], text_ls[2]) + self.sys_info("创建目录成功!") + else: + self.sys_info("请检查输入格式{'str','int','int'}!") + else: + self.sys_info("文件名重复!") + else: + self.sys_info("目前正在执行磁盘修改任务!") + + def show_path_info(self, ): # 显示文件目录信息 + self.canvas.delete("creat_path") # 画新图前元素清空 + start_x = 580 + start_y = 96 + tags = "creat_path" # 删除标签 + word_high = 26 # 字高 + self.path_delete_image = self.image_transition("img/删除.png") + self.path_edit_image = self.image_transition("img/编辑.png") + + for i, item in enumerate(self.FolderItems): + item = [str(n) for n in item] + text = "\t".join(item) # 制表符加工 + if start_y + i * word_high < 250: # 超出范围限制显示 + self.canvas.create_text(start_x, start_y + i * word_high, anchor=tk.NW, text=text, font=("Arial", 14), + fill="white", tags=tags) + self.set_canvas_button([start_x + 440, start_y + i * word_high], self.path_edit_image, + lambda n=i, x=start_x, y=start_y: self.path_info_edit(n, x, y), tags, + bg="#434FC5") + self.set_canvas_button([start_x + 470, start_y + i * word_high], self.path_delete_image, + lambda n=i: self.path_info_delete(n), tags, bg="#434FC5") + else: + self.sys_info("文件显示将溢出") + break + + def delete_edit_file(self, index): # 点击编辑后就先清空当前文件的保留 + first_block = self.FolderItems[index][1] # 获取选中的文件的第一块位置 + file_name = self.FolderItems[index][0] + fat_table = read_sim_fat(int(first_block), self.SimFAT) # 获取文件的fat表 + file_name_set.remove(file_name) + for fat in fat_table: + row = fat // 10 + column = fat % 10 + self.SimFAT[row][column] = 0 + self.SimDisk[row][column] = 0 + self.fat_unique_set.remove(fat) + + def path_info_edit(self, index, x, y): + print("文件修改") + if self.file_modi_tag: + self.special_info("正在修改文件,\n修改完成请保存。") + tags = "creat_path" # 删除标签 + word_high = 26 # 字高 + file_name = self.FolderItems[index][0] + first_block = self.FolderItems[index][1] + blocks = self.FolderItems[index][2] + mark_char = self.FolderItems[index][3] + self.path_save_image = self.image_transition("img/保存弹窗.png") + self.path_cancel_image = self.image_transition("img/取消弹窗.png") + y = y + index * word_high + self.file_name = self.set_canvas_entry(x, y, 6, file_name, tags) # 显示entry组件,输入字符 + self.first_block = self.set_canvas_entry(x + 80, y, 6, first_block, tags) + self.blocks = self.set_canvas_entry(x + 160, y, 6, blocks, tags) + self.mark_char = self.set_canvas_entry(x + 240, y, 6, mark_char, tags) + self.set_canvas_button([x + 330, y], self.path_save_image, tags=tags, bg="#434FC5", + command=lambda: self.path_info_edit_save(index)) + self.set_canvas_button([x + 380, y], self.path_cancel_image, tags=tags, bg="#434FC5", + command=lambda: self.path_info_edit_cancel()) + self.sys_info(f"{file_name} 文件修改中...") + else: + self.sys_info("未开启文件校验流程,无法修改文件") + # def path_info_edit_save(self, index): # 文件项编辑的保存 + # if self.file_modi_tag and not self.clear_tag: + # file_name = self.file_name.get() + # first_block = self.first_block.get() + # block_num = self.blocks.get() + # old_first_block = int(self.FolderItems[index][1]) + # old_fat_table = read_sim_fat(int(old_first_block), self.SimFAT) # 获取文件的fat表 + # if file_name != "" and first_block != "" and block_num != "": + # if first_block.isdigit() and block_num.isdigit(): + # if int(first_block) not in self.fat_unique_set or int(first_block) in old_fat_table: + # + # if len(self.fat_unique_set) + int(block_num) - len(old_fat_table) <= 100: + # b_label = self.FolderItems[index][3] + # self.delete_edit_file(index) # 执行前先删除旧的记录 + # self.FolderItems[index] = [file_name, first_block, block_num, b_label] + # fat_arr = self.generate_fat_array(int(first_block), int(block_num)) # 重新生成fat表 + # file_name_set.add(file_name) + # self.load_files_list(fat_arr, b_label) + # self.show_path_info() + # self.sys_info("修改成功!") + # else: + # self.sys_info("磁盘空间不足!") + # else: + # self.sys_info("首块位置已被占用!") + # else: + # self.sys_info("请输入正整数!") + # else: + # self.sys_info("修改值不能为空!") + # else: + # self.sys_info("目前正在执行磁盘修改任务!") + + def path_info_edit_save(self, index): # 文件项编辑的保存 + print("文件保存") + if self.file_modi_tag and not self.clear_tag: + self.special_info("文件已保存,可以开始校验。") + file_name = self.file_name.get() # 文件名 + first_block = self.first_block.get() # 磁盘首块 + if first_block.isdigit(): + first_block = int(first_block) + block_num = self.blocks.get() # 磁盘块数 + mark_char = self.mark_char.get() # 磁盘标签 + self.FolderItems[index] = [file_name, first_block, block_num, mark_char] + file_name_set.add(file_name) + self.show_path_info() + self.sys_info("修改成功!") + else: + self.sys_info("未开启文件修改任务") + + def path_info_edit_cancel(self): + self.show_path_info() + self.sys_info("已取消操作!") + + def path_info_delete(self, index): + if self.clear_tag: + self.delete_edit_file(index) # 清空disk和fat + file_info = self.FolderItems.pop(index) # 删除该索引指向的元素 + blocks_label_set.remove(file_info[3]) + self.canvas.delete("fk3") + self.show_path_info() # 重新显示文件信息 + self.show_all_fat() + self.show_all_disk() + self.sys_info(f"文件 {file_info[0]} 删除成功!") + else: + self.sys_info("正在进行校验操作,无法执行删除操作!") + + def select_fat_unique(self): + while True: # 确保每次不同的字符被选中 + unique_num = random.randint(0, 99) + if unique_num not in self.fat_unique_set: + return unique_num + if len(self.fat_unique_set) >= 100: + return None + + def generate_fat_array(self, first_block: int, block_num: int): # 生成fat表文件列表 + fat_arr = [first_block] + self.fat_unique_set.update(fat_arr) + for i in range(block_num - 1): + while True: + num = random.randint(1, 99) + if len(self.fat_unique_set) >= 101: + num = None + break + if num not in self.fat_unique_set: + self.fat_unique_set.add(num) + break + if num: + fat_arr.append(num) + else: + break + return fat_arr + + def save_file(self, file_name=None, f_block=None, blocks=None): + print("保存文件") + if file_name: + file_name = file_name + else: + file_name = self.file_name_label.get() + + if blocks: + blocks = blocks + else: + blocks = self.blocks_num_label.get() + + if self.creating: # 如果保存时没有创建过,先创建 + self.creat_file(file_name, f_block, blocks) # 保存的同时执行创建 + + if self.check: + if f_block: + f_block = int(f_block) + else: + f_block = self.select_fat_unique() + fat_arr = self.generate_fat_array(f_block, int(blocks)) # 生成fat表 + self.FolderItems.append([file_name, f_block, blocks, self.code]) # 添加到文件夹 + file_name_set.add(file_name) # 添加唯一性文件名集合 + self.fat_unique_set.update(fat_arr) # 将占用的磁盘位置信息添加进唯一集合,防止重复取数 + self.load_files_list(fat_arr, self.code) # 根据fat表向磁盘装载文件数据并显示 + self.show_path_info() # 保存后显示文件夹 + self.creating = True # 上一次保存执行完成后才能开始二次执行 + self.sys_info("保存成功") + + def restart(self): + global blocks_label_set + global file_name_set + self.modi_fat_save() + self.modi_block_save() + self.save_occupy() + self.canvas.delete("creat_path") + self.canvas.delete("fk3") + self.canvas.delete("fat_tag") + self.canvas.delete("fat_disk") + self.canvas.delete("label_disk") + self.canvas.delete("info") + + self.massages = [] # 清空消息 + self.FolderItems = [] # 清空文件项 + blocks_label_set = set() # 块标签集合清空 + file_name_set = set() # 唯一性文件名清空 + self.fat_unique_set = {0} # 重置fat唯一位置检查集合 + self.SimFAT = initialize_simfat() # 重置fat表 + self.SimDisk = initialize_simdisk() # 重置磁盘 + self.sim_fat_copy = None # fat表深拷贝初始化 + self.ex_disk_oc = True # 交替显示保存占用和添加占用标志 + self.ex_disk_la = True # 修改保存标签和清除标签的标志 + self.sim_disk_copy = None # 磁盘块深拷贝初始化 + self.block_modi_tag = False # 磁盘块修改标志置否 + self.block_modi_lb = None # 磁盘块标签值初始化 + self.old_key = None # FAT表上一次的记录值 + self.fat_modi_num = None # 打开下一个FAT单元格之前的修改数值 + self.fat_modi_tag = False # 修改状态标签,为True时进入修改状态 + self.clear_tag = True # 清除标签,让标签清理和fat清理操作互斥 + self.check = None # 检查磁盘条件 + self.code = None # 当前磁盘块标签字母 + self.creating = True # 正在创建的状态 + self.file_modi_tag = False # 文件修改状态 + self.sim_file_copy = None # 仿真文件复制临时列表,用于校验 + + self.file_save_button.config(state="normal") # 禁用一部分按键 + self.fat_check_button.config(state="normal") + self.disk_check_button.config(state="normal") + self.creat_path_button.config(state="normal") + self.add_occupy_button.config(state="normal") + self.clear_file_button.config(state="normal") + self.file_check_button.config(state="normal") + + try: + self.last_step.destroy() + self.next_step.destroy() + except: + pass + self.sys_info("重置成功!") + self.special_info("重置成功!") + + + def file_check(self): + global file_name_set + if self.file_modi_tag: + sum = 0 + for i in range(len(self.FolderItems)): + if self.FolderItems[i][1:] == self.sim_file_copy[i][1:]: + sum+=1 + file_name_set.add(self.FolderItems[i][0]) # 将新文件名添加到唯一结构 + if sum == len(self.FolderItems): + self.sys_info("校验正确") + self.special_info("恭喜!\n文件校验成功!") + self.sim_file_copy = None # 校验正确才值无 + else: + self.sys_info("校验错误。") + self.special_info("文件校验失败。") + + self.file_modi_tag = False + self.clear_tag = True + else: + self.sys_info("没有开启文件校验流程,无法校验。") + + + def clear_file_label(self): + """清除FAT表""" + global file_name_set + print("清除文件标签") + if len(self.FolderItems)>0: + if self.clear_tag: + self.special_info("正在进行文件校验!\n请点击目录项的铅笔图标。\n修改目录项。") + self.file_modi_tag = True + self.canvas.delete("creat_path") + self.clear_tag = False # 锁定文件校验状态 + if not self.sim_file_copy: + self.sim_file_copy = copy.deepcopy(self.FolderItems) # 深拷贝复制一份原正确列表并保存为复制对象 + file_name_set = set() + t0 = list() + for i in range(len(self.FolderItems)): + item = ["-","-","-","-"] + t0.append(item) + self.FolderItems = t0 + self.show_path_info() + self.sys_info("文件清除成功!") + else: + self.sys_info("正在执行校验任务,无法清除目录项!") + else: + self.sys_info("文件夹无文件无法清除目录!") + + + + def manual_save(self): + print("手动保存") + self.restart() + if self.current_step: + self.last_step.destroy() + self.next_step.destroy() + + self.last_step = tk.Button(self.canvas_child, text="上一步", command=self.last_step_func) + self.canvas_child.create_window([80, 180], anchor="nw", window=self.last_step) + self.last_step.config(state="disabled") + + self.next_step = tk.Button(self.canvas_child, text="下一步", command=self.next_step_func) + self.canvas_child.create_window([160, 180], anchor="nw", window=self.next_step) + + self.current_step = 1 + self.file_info_edit() # 开启构造文件夹操作 + self.file_save_button.config(state="disabled") # 禁用一部分按键 + self.fat_check_button.config(state="disabled") + self.disk_check_button.config(state="disabled") + self.creat_path_button.config(state="disabled") + self.add_occupy_button.config(state="disabled") + self.clear_file_button.config(state="disabled") + self.file_check_button.config(state="disabled") + + def last_step_func(self): + print("上一步") + if self.current_step == 2: + print(1) + self.current_step = 1 + # 开启文件夹修改 + self.last_step.config(state="disabled") + self.file_info_edit() # 开启文件夹构造操作 + self.modi_fat_save() + + elif self.current_step == 3: + print(2) + self.current_step = 2 + # 开启FAT修改 + self.modi_block_save() + self.clear_fat_label() + self.next_step.config(state="normal") + self.next_step.config(text="下一步") + + elif self.current_step == 4: + self.current_step =3 + print(3) + # 开启磁盘修改 + self.clear_disk_label() + self.next_step.config(text="完 成") + + def next_step_func(self): + print("下一步") + if self.current_step == 1: + print("2") + self.current_step = 2 + self.last_step.config(state="normal") + # 开启FAT修改 + self.file_info_save() # 保存文件夹构造,并将文件信息添加到类属性self.FolderItems + self.clear_fat_label() # 清除FAT表 + # self.modi_fat() + + elif self.current_step == 2: + print("3") + self.current_step = 3 + self.modi_fat_save() + self.clear_disk_label() + # 开启磁盘修改 + # self.next_step.config(state="disabled") + self.next_step.config(text="完 成") + + elif self.current_step == 3: + print("4") + self.current_step = 4 + self.modi_block_save() + # 完成 + # self.next_step.config(text="完 成") + self.next_step.config(text="校 验") + + elif self.current_step == 4: + # 校验 + # self.next_step.config(text="校 验") + self.save_check() + + def save_check(self): + folder_item = self.FolderItems + fat_table = self.SimFAT + block_table = self.SimDisk + f_num = 0 + for folders in folder_item: + num = 0 + name = folders[0] + first = folders[1] + if first.isdigit(): + blocks = int(folders[2]) + label = folders[3] + fat = read_sim_fat(first, fat_table) + if len(fat) == int(blocks): + num += 1 + for i, loca in enumerate(fat): + row = loca // 10 + col = loca % 10 + if block_table[row][col] == f"{label}{i+1}": + num += 1 + if i < len(fat)-1: + if fat_table[row][col] == fat[i+1]: + num += 1 + elif i == len(fat)-1: + if fat_table[row][col] == "FF": + num += 1 + if num == 2*len(fat)+1: + self.sys_info(f"{name}校验正确!") + else: + self.sys_info(f"{name}校验错误!") + f_num += 1 + else: + self.sys_info(f"{name}校验错误!") + if f_num == len(self.FolderItems): + self.special_info("校验成功") + try: + self.last_step.destroy() + self.next_step.destroy() + except: + pass + else: + self.special_info("校验失败") + + def file_info_edit(self): + print("手动保存文件夹文件") + if self.current_step ==1: + self.special_info("手动保存模式。\n请先在初始区创建文件\n然后再完善文件信息。\n最后点击下一步。") + tags = "creat_path" # 删除标签 + self.canvas.delete(tags) + x = 580 + y = 96 + self.file_name = self.set_canvas_entry(x, y, 6, "", tags) # 显示entry组件,输入字符 + self.first_block = self.set_canvas_entry(x + 80, y, 6, "", tags) + self.blocks = self.set_canvas_entry(x + 160, y, 6, "", tags) + self.mark_char = self.set_canvas_entry(x + 240, y, 6, " ", tags) + + def file_info_save(self): + self.special_info("文件保存成功\n现在开始添加文件分配表。") + if self.FolderItems != []: + self.FolderItems.pop() + file_name = self.file_name.get() # 文件名 + first_block = self.first_block.get() # 磁盘首块 + if first_block.isdigit(): + first_block = int(first_block) + block_num = self.blocks.get() # 磁盘块数 + mark_char = self.mark_char.get() # 磁盘标签 + self.FolderItems.append([file_name, first_block, block_num, mark_char]) + file_name_set.add(file_name) # 添加唯一文件名 + blocks_label_set.add(mark_char) # 添加磁盘唯一块标志 + + tags = "creat_path" # 删除标签 + self.canvas.delete(tags) + for i, item in enumerate(self.FolderItems): + item = [str(n) for n in item] + text = "\t".join(item) # 制表符加工 + self.canvas.create_text(580, 96, anchor=tk.NW, text=text, font=("Arial", 14), + fill="white", tags=tags) + self.sys_info("修改成功!") + + def clear_fat_label(self): + print("清除表单项") + self.special_info("正在进行FAT校验!\n请点击修改表单项。\n修改FAT表。") + self.fat_modi_tag = True # 开启FAT修改标签 + if self.clear_tag: + self.canvas.delete("fat_tag") + self.clear_tag = False + if not self.sim_fat_copy: + self.sim_fat_copy = copy.deepcopy(self.SimFAT) # 深拷贝复制一份原正确列表并保存为复制对象 + self.SimFAT = initialize_simfat() # 同时清空原FAT表 + self.sys_info("清除成功!") + + else: + self.sys_info("正在执行校验任务,无法清除表单项!") + + def modi_fat(self): + if self.fat_modi_tag: + self.special_info("正在修改FAT表。\n点击FAT表对应区域修改值。\n完成后保存表单项。") + if not self.sim_fat_copy and self.fat_modi_tag: + self.sim_fat_copy = copy.deepcopy(self.SimFAT) # 深拷贝复制一份原正确列表并保存为复制对象 + else: + self.sys_info("未开启FAT校验流程。") + + def modi_fat_entry(self, row, column, lt_top): + default = self.SimFAT[row][column] + if self.fat_modi_num and self.old_key: + if self.fat_modi_num.get().isdigit() or self.fat_modi_num.get().upper() == "FF": + if self.fat_modi_num.get().isdigit(): + self.SimFAT[self.old_key[0]][self.old_key[1]] = int(self.fat_modi_num.get()) + else: + self.SimFAT[self.old_key[0]][self.old_key[1]] = "FF" + self.sys_info(f"{self.old_key} -> {self.fat_modi_num.get()}添加成功!") + else: + self.sys_info("请输入正整数,或FF!") + + self.canvas.delete("fat_entry") + self.fat_modi_num = self.set_canvas_entry(lt_top[0] + 8, lt_top[1] + 8, 2, default, "fat_entry") + self.old_key = [row, column] + self.show_all_fat() + + def modi_fat_save(self): + print("保存表单项") + if self.fat_modi_tag: + self.canvas.delete("fat_entry") + self.fat_modi_tag = False # 修改标志置否保存后就不再能修改 + self.clear_tag = True # 保存后清除项就置真 + if self.fat_modi_num and self.old_key: + if self.fat_modi_num.get().isdigit() or self.fat_modi_num.get().upper() == "FF": + if self.fat_modi_num.get().isdigit(): + self.SimFAT[self.old_key[0]][self.old_key[1]] = int(self.fat_modi_num.get()) + else: + self.SimFAT[self.old_key[0]][self.old_key[1]] = "FF" + else: + self.sys_info("请输入正整数,或FF!") + self.show_all_fat() + self.old_key = None + + for i in range(10): + for n in range(10): + if self.SimFAT[i][n] != 0: + num = i * 10 + n + self.fat_unique_set.add(num) + self.sys_info("保存表单成功!") + self.special_info("FAT 保存成功!\n可以开始校验。") + self.fat_modi_tag = False # 修改标志置否保存后就不再能修改 + else: + self.sys_info("未开启FAT校验流程。") + + def fat_checkout(self): + print("FAT校验") + if self.sim_fat_copy and not self.fat_modi_tag: + num = 0 + tag = False + for i in range(10): + for n in range(10): + num += 1 + if self.SimFAT[i][n] != self.sim_fat_copy[i][n]: + self.sys_info(f"校验失败\n{i}行{n}列错误") + tag = True + break + if tag: + break + + if num == 100: + self.sys_info("校验正确") + self.special_info("恭喜!\nFAT校验正确!") + + self.sim_fat_copy = None + + else: + self.sys_info("未完成修改操作,不可校验") + + def clear_disk_label(self): + print("清除标签") + if self.clear_tag: + self.block_modi_tag = True + self.special_info("正在进行磁盘块校验。\n请点击修改标签,\n补充清除的磁盘块标签。") + self.canvas.delete("block_entry") + self.canvas.delete("label_disk") + # self.canvas.delete("") + self.clear_tag = False # 将清除标志置否,防止其他模块改动 + if not self.sim_disk_copy: + self.sim_disk_copy = copy.deepcopy(self.SimDisk) # 复制一份原正确列表并保存为复制对象 + + for i in range(10): + for j in range(10): + if self.SimDisk[i][j] != 0: + self.SimDisk[i][j] = 0 + self.sys_info("清除成功!") + self.show_all_disk() + else: + self.sys_info("正在执行校验任务,无法清除磁盘模块标签。") + + + def modi_block_lb(self): # 修改标签 + print("修改标签") + if self.block_modi_tag: + self.special_info("正在修改磁盘块。\n点击磁盘模块区域修改值。\n完成后保存标签。") + self.clear_tag = False # 修改磁盘标签时冻结文件分配表的按钮 + if not self.sim_disk_copy: + self.sim_disk_copy = copy.deepcopy(self.SimDisk) # 深度拷贝数组 + + self.ex_disk_la = False + self.canvas.delete("prl") + self.exchange_button_disk_label() + else: + self.sys_info("未开启磁盘块校验流程。") + + def modi_block_entry(self, row, column, lt_top): + default = self.SimDisk[row][column] + + if self.block_modi_lb: + label = self.block_modi_lb.get().upper() + if label != "0": + if re.match(r'^[A-Za-z]\d+$', label): # 正则表达式将匹配如 "A1"、"b2"、"Z9" 等形式的字符串 + self.SimDisk[self.old_key[0]][self.old_key[1]] = label + self.sys_info(f"{self.old_key} -> {label}添加成功!") + else: + self.sys_info("请输入正确格式,如:A1!") + + self.canvas.delete("block_entry") + self.block_modi_lb = self.set_canvas_entry(lt_top[0] + 2, lt_top[1] + 10, 3, default, "block_entry", 12) + self.block_modi_lb.select_range(0, tk.END) # 使Entry组件获得焦点(选中),以便可以直接修改值 + self.old_key = [row, column] + self.show_all_disk() + + def modi_block_save(self): + print("保存标签") + if self.block_modi_tag: + self.canvas.delete("block_entry") + self.ex_disk_la = True + self.canvas.delete("psl") + self.exchange_button_disk_label() + if self.block_modi_lb: + label = self.block_modi_lb.get().upper() + if label != "0": + if re.match(r'^[A-Za-z]\d+$', label): # 正则表达式将匹配如 "A1"、"b2"、"Z9" 等形式的字符串 + self.SimDisk[self.old_key[0]][self.old_key[1]] = label + self.sys_info(f"{self.old_key} -> {label}添加成功!") + else: + self.sys_info("请输入正确格式,如:A1!") + + for i in range(10): + for n in range(10): + if self.SimDisk[i][n] != 0 and self.SimDisk[i][n] != "": + num = i * 10 + n + code = self.SimDisk[i][n][0] # 取第一个字母 + blocks_label_set.add(code) # 添加字母到字母唯一集合 + self.fat_unique_set.add(num) # 将被占用的位置添加到唯一FAT表中防止被选中 + + self.block_modi_lb = False # 修改标签置否。 + self.show_all_disk() + self.block_modi_tag = False # 磁盘修改标签置否 + self.clear_tag = True + self.special_info("磁盘块已保存。\n可以开始校验。") + self.sys_info("磁盘块保存成功!") + else: + self.sys_info("未开启磁盘校验流程") + + def add_occupy(self): + print("添加占用") + self.ex_disk_oc = False + self.canvas.delete("pao") + self.exchange_button_disk_occupy() + self.sys_info("正在添加占用...") + self.special_info("正在添加占用。") + + def add_occupy_click(self, x, y): + if not self.ex_disk_oc: + for key, block_lt in self.blocks_position_mapping.items(): + if block_lt[0] < x < block_lt[0] + 43 and block_lt[1] < y < block_lt[1] + 43: + self.SimDisk[key[0]][key[1]] = "" + self.SimFAT[key[0]][key[1]] = "X" + print(key[0], key[1]) + self.show_all_disk() + self.show_all_fat() + self.sys_info(f"{key}添加成功") + + def disk_checkout(self): + print("Disk校验") + if self.sim_disk_copy and not self.block_modi_tag: + num = 0 + tag = False + for i in range(10): + for n in range(10): + num += 1 + if self.SimDisk[i][n] != self.sim_disk_copy[i][n]: + if self.SimDisk[i][n] != "": + self.sys_info(f"校验失败\n{i}行{n}列错误") + tag = True + break + if tag: + break + if num == 100: + self.special_info("恭喜!\n磁盘校验正确!") + self.sys_info("校验正确") + self.sim_disk_copy = None + else: + self.sys_info("未进行修改操作,不可校验") + + def save_occupy(self): + print("保存占用") + self.ex_disk_oc = True + self.canvas.delete("pso") + self.exchange_button_disk_occupy() + + for i in range(10): + for n in range(10): + if self.SimDisk[i][n] != 0: + num = i * 10 + n + self.fat_unique_set.add(num) + self.sys_info("保存占用成功!") + self.special_info("保存占用成功!") + + def on_left_click(self, event, ): + x = event.x + y = event.y + print(x, y) + if self.fat_modi_tag: + for key, fat_lt in self.fat_table_position_mapping.items(): + if fat_lt[0] < x < fat_lt[0] + 43 and fat_lt[1] < y < fat_lt[1] + 43: + self.modi_fat_entry(key[0], key[1], fat_lt) + + if self.block_modi_tag: + for key, block_lt in self.blocks_position_mapping.items(): + if block_lt[0] < x < block_lt[0] + 43 and block_lt[1] < y < block_lt[1] + 43: + self.modi_block_entry(key[0], key[1], block_lt) + + self.add_occupy_click(x, y) + + # pprint(self.SimFAT) + + def show_real_disk(self, title, sector): + child_window = tk.Toplevel(self.root) + child_window.title(title) + + child_window1 = tk.Toplevel(self.root) + child_window1.title(f"{title}_字节解析") + + sector_num, Bytes = sector + canvas = tk.Canvas(child_window, width=750, height=830, bg="white", ) + canvas1 = tk.Canvas(child_window1, width=750, height=830, bg="white", ) + BYTES_PER_LINE = 16 # 每行字节数 + n = 0 + s = 0 + for byte in range(16): + if s % 9 == 0: + s = s + 1 + canvas.create_text(100 + s * 35, 20 + n * 24, text=f"{byte:02X}", anchor="nw", fill="red", + font=("Arial", 14)) + canvas1.create_text(100 + s * 35, 20 + n * 24, text=f"{byte:02X}", anchor="nw", fill="red", + font=("Arial", 14)) + s += 1 + n += 1 + for i in range(0, len(Bytes), BYTES_PER_LINE): + line_data = Bytes[i:i + BYTES_PER_LINE] + print(f"{sector_num * 32 + i:08X}:", end=" ") + canvas.create_text(20, 20 + n * 24, text=f"{sector_num * 32 + i:08X}:", anchor="nw", fill="red",font=("Arial", 14)) + canvas1.create_text(20, 20 + n * 24, text=f"{sector_num * 32 + i:08X}:", anchor="nw", fill="red",font=("Arial", 14)) + s = 0 + for byte in line_data: + print(f"{byte:02X}", end=" ") + print(chr(byte), end=" ") + if s % 9 == 0: + s = s + 1 + canvas.create_text(100 + s * 35, 20 + n * 24, text=f"{byte:02X}", anchor="nw", fill="black",font=("Arial", 14)) + canvas1.create_text(100 + s * 35, 20 + n * 24, text=f"{chr(byte)}", anchor="nw", fill="black",font=("Arial", 14)) + s += 1 + print() + n += 1 + canvas.pack(fill=tk.BOTH, expand=True) + canvas1.pack(fill=tk.BOTH, expand=True) + self.sys_info(f"正在查看{title}") + + +if __name__ == '__main__': + root = tk.Tk() + root.resizable(False, False) # 禁止用户调整窗口大小 + main = InterfaceFile(root) + # root.after(60000, close_window) + root.mainloop() + diff --git a/__pycache__/files_sys_sim.cpython-311.pyc b/__pycache__/files_sys_sim.cpython-311.pyc new file mode 100644 index 0000000..3ce2c41 Binary files /dev/null and b/__pycache__/files_sys_sim.cpython-311.pyc differ diff --git a/__pycache__/read_bin.cpython-311.pyc b/__pycache__/read_bin.cpython-311.pyc new file mode 100644 index 0000000..bc36a40 Binary files /dev/null and b/__pycache__/read_bin.cpython-311.pyc differ diff --git a/disk_read.py b/disk_read.py new file mode 100644 index 0000000..28e229b --- /dev/null +++ b/disk_read.py @@ -0,0 +1,52 @@ +# -*- encoding: utf-8 -*- +""" +@File : disk_read.py +@License : (C)Copyright 2021-2023 + +@Modify Time @Author @Version @Description +------------ ------- -------- ----------- +2023/10/9 10:04 zart20 1.0 None +""" +import os + +# 定义常量 +SECTOR_SIZE = 512 # 扇区大小 +BYTES_PER_LINE = 16 # 每行字节数 +# MAX_SECTORS_TO_READ = 15927 # 要读取的最大扇区数量 +MAX_SECTORS_TO_READ = 0 +# 打开设备文件 +drive_letter = "I:" # 请替换为你要操作的磁盘 +file_path = f"\\\\.\\{drive_letter}" # 设备文件路径 + +try: + with open(file_path, 'rb') as disk: + sector_number = 0 # 起始扇区号 + byte_offset = 0 # 字节偏移量初始化 + sectors_read = 0 # 已读取的扇区数量 + + while sectors_read <= MAX_SECTORS_TO_READ: + # 读取扇区数据 + disk.seek(sector_number * SECTOR_SIZE) + sector_data = disk.read(SECTOR_SIZE) + + # 输出扇区数据 + print(f"扇区号:{sector_number}") + for i in range(0, len(sector_data), BYTES_PER_LINE): + line_data = sector_data[i:i + BYTES_PER_LINE] + print(f"{byte_offset + i:08X}:", end=" ") # 输出字节偏移量(16进制) + for byte in line_data: + print(f"{byte:02X}", end=" ") # 输出每个字节的16进制表示 + + print() # 换行 + + # 更新扇区号,读取下一个扇区 + sector_number += 1 + byte_offset += len(sector_data) # 累加字节偏移量 + sectors_read += 1 + +except PermissionError: + print("没有足够的权限来访问磁盘。请以管理员身份运行程序。") +except FileNotFoundError: + print(f"找不到设备文件:{file_path}") +except Exception as e: + print(f"发生错误:{e}") diff --git a/disk_to_bin.py b/disk_to_bin.py new file mode 100644 index 0000000..0f7bd94 --- /dev/null +++ b/disk_to_bin.py @@ -0,0 +1,43 @@ +# -*- encoding: utf-8 -*- +""" +@File : disk_to_bin.py +@License : (C)Copyright 2021-2023 + +@Modify Time @Author @Version @Description +------------ ------- -------- ----------- +2023/10/9 16:01 zart20 1.0 None +""" + +# 定义常量 +SECTOR_SIZE = 512 # 扇区大小 +BYTES_PER_LINE = 16 # 每行字节数 +MAX_SECTORS_TO_READ = 15927 # 要读取的最大扇区数量 +# MAX_SECTORS_TO_READ = 3 +# 打开设备文件 +drive_letter = "I:" # 请替换为你要操作的磁盘 +file_path = f"\\\\.\\{drive_letter}" # 设备文件路径 + +with open("output.bin","wb+") as out: + + with open(file_path, 'rb') as disk: + sector_number = 0 # 起始扇区号 + byte_offset = 0 # 字节偏移量初始化 + sectors_read = 0 # 已读取的扇区数量 + + while sectors_read <= MAX_SECTORS_TO_READ: + # 读取扇区数据 + disk.seek(sector_number * SECTOR_SIZE) + sector_data = disk.read(SECTOR_SIZE) + + print(sector_data) + out.write(sector_data) + + for byte in sector_data: + print(f"{byte:02X}", end=" ") # 输出每个字节的16进制表示 + + print() # 换行 + + sector_number += 1 + byte_offset += len(sector_data) # 累加字节偏移量 + sectors_read += 1 + \ No newline at end of file diff --git a/disk_to_csv.py b/disk_to_csv.py new file mode 100644 index 0000000..77ab52b --- /dev/null +++ b/disk_to_csv.py @@ -0,0 +1,62 @@ +# -*- encoding: utf-8 -*- +""" +@File : disk_read.py +@License : (C)Copyright 2021-2023 + +@Modify Time @Author @Version @Description +------------ ------- -------- ----------- +2023/10/9 10:04 zart20 1.0 None +""" +import os +import pandas as pd + +columns = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'] +indexs = [] + +my_dict = {i: [] for i in columns} + +# 定义常量 +SECTOR_SIZE = 512 # 扇区大小 +BYTES_PER_LINE = 16 # 每行字节数 +MAX_SECTORS_TO_READ = 15927 # 要读取的最大扇区数量 +# MAX_SECTORS_TO_READ = 10 +# 打开设备文件 +drive_letter = "I:" # 请替换为你要操作的磁盘 +file_path = f"\\\\.\\{drive_letter}" # 设备文件路径 + +try: + with open(file_path, 'rb') as disk: + sector_number = 0 # 起始扇区号 + byte_offset = 0 # 字节偏移量初始化 + sectors_read = 0 # 已读取的扇区数量 + + while sectors_read <= MAX_SECTORS_TO_READ: + # 读取扇区数据 + disk.seek(sector_number * SECTOR_SIZE) + sector_data = disk.read(SECTOR_SIZE) + + # 输出扇区数据 + for i in range(0, len(sector_data), BYTES_PER_LINE): + line_data = sector_data[i:i + BYTES_PER_LINE] + indexs.append(f"{byte_offset + i:08X}:") + n = 0 + for byte in line_data: + my_dict[columns[n]].append(f"{byte:02X}") + n += 1 + + # 更新扇区号,读取下一个扇区 + sector_number += 1 + byte_offset += len(sector_data) # 累加字节偏移量 + sectors_read += 1 + +except PermissionError: + print("没有足够的权限来访问磁盘。请以管理员身份运行程序。") +except FileNotFoundError: + print(f"找不到设备文件:{file_path}") +except Exception as e: + print(f"发生错误:{e}") + +df = pd.DataFrame(my_dict, index=indexs) +print(df) +df.to_csv("output.csv") +print('输出完毕') \ No newline at end of file diff --git a/files_sys_sim.py b/files_sys_sim.py new file mode 100644 index 0000000..7afb8f2 --- /dev/null +++ b/files_sys_sim.py @@ -0,0 +1,230 @@ +# -*- encoding: utf-8 -*- +''' +@File : files_sys_sim.py +@License : (C)Copyright 2018-2022 + +@Modify Time @Author @Version @Desciption +------------ ------- -------- ----------- +2023/8/15 10:41 zart20 1.0 None +''' +import copy +import random +from pprint import pprint + +######### 7.1 ################# +blocks_label_set = set() +def get_unique_tag(): # 获取唯一字母标签 + for ascii_code in range(65,91): + character = chr(ascii_code) + if character not in blocks_label_set: + blocks_label_set.add(character) + return character + +def initialize_fileblock(block_num, code): + files = [] + for n in range(int(block_num)): + files.append(f"{code}{n+1}") + if code == "Z": + blocks_label_set.clear() + return files + +def initialize_folderitem(): + folder_items = [] + for i in range(3): + name = f"f{i}" + first = random.randint(1,100) + block_num = random.randint(1,11) + item = [name, first,block_num] + folder_items.append(item) + return folder_items + +def file_fat_mapping(Fileblock): + pass + + +def initialize_simdisk(): + sim_disk = [[0] *10 for _ in range(10)] + return sim_disk + +def initialize_simfat(): + sim_fat = [[0] * 10 for _ in range(10)] + sim_fat[0][0] = 100 + return sim_fat + + +######### 7.2 ################# +# 假设一个磁盘块大小为64KB(以字节为单位) +BLOCK_SIZE = 64 + +# 初始化SimFAT表元素长度,为10则是100块磁盘块 +NUM_ENTRIES = 10 + +def count_available_space(sim_fat): + for i in range(1, len(sim_fat)): # 构造操作数组的操作 + for j in range(1, len(sim_fat)): + if random.randint(1,10) > 3: # 模拟40% 概率的填入率, + sim_fat[i][j] = random.choice([f"{n:02}" for n in range(100)] + ['FF']) # 给每个位置填入随机块 + + num_available_blocks = sum(row.count(0) for row in sim_fat) # 统计为0的块 + return num_available_blocks * BLOCK_SIZE + + +######### 7.3 ################# +BLOCK_NUM = 7 +LAST_BLOCK = "FF" +FIRST_BLOCK = 8 # 第一块fat位置 + +def generate_chain_structure(): + sim_fat = ["0"] * BLOCK_NUM # 文件块的大小 + used_blocks = {"00", FIRST_BLOCK} # 用于存储已经被占用的块位置,且预置00块和第一块为已占用状态 + + for i in range(len(sim_fat) - 1): + while True: + location = random.randint(0, 99) + if location not in used_blocks: # 防止已经被占用的快被重新占用 + sim_fat[i] = location + used_blocks.add(location) + break + + sim_fat[-1] = LAST_BLOCK + chain_structure = [] # 链结构 + for i, value in enumerate(sim_fat): + if i == 0: + print(f"SimFAT[{FIRST_BLOCK}] -> {value}") + item = {FIRST_BLOCK: value} # 构建链结构 + else: + print(f"SimFAT[{sim_fat[i-1]}] -> {value}") + item = {sim_fat[i-1]: value} # 构建链结构 + chain_structure.append(item) + return chain_structure + +# if __name__ == "__main__": +# print(generate_chain_structure()) + + +######### 7.4 ################# + +sim_fat_chain = [{'08': '02'}, {'02': '56'}, {'56': '31'}, {'31': '55'}, {'55': '67'}, {'67': '74'}, {'74': 'FF'}] + +def get_disk_block_order(sim_fat_chain, start_block): + disk_order = [start_block] + current_block = start_block # 当前块 + + while current_block != "FF": + next_block = None + for item in sim_fat_chain: # item是字典 + if current_block in item: + next_block = item[current_block] # 当前键的值是下一个块的键 + break + if next_block is None: # 当没有下一个块时退出循环 + break + disk_order.append(next_block) + current_block = next_block # 更新当前块 + return disk_order + +# print(get_disk_block_order(sim_fat_chain,FIRST_BLOCK)) + +######### 7.5 ################# + +class Folder: + def __init__(self): + self.folder_items = [] + + def insert_folder_item(self, file_name, first_block, num_blocks): # 插入一个目录项 + item = { + "file_name": file_name, + "first_block": first_block, + "num_blocks": num_blocks + } + self.folder_items.append(item) + return item + + def retrieve_folder_item(self, target_name): # 检索一个目录项 + for item in self.folder_items: + if item["file_name"] == target_name: + return item + return None + + def delete_folder_item(self, target_name): # 删除一个目录项 + for item in self.folder_items: + if item["file_name"] == target_name: + self.folder_items.remove(item) + return True + return False + + def print_folder_items(self): + for item in self.folder_items: + print(f"File: {item['file_name']} - First Block: {item['first_block']} - Num Blocks: {item['num_blocks']}") + +# 通过第一块磁盘块的位置读取整个fat表 +def read_sim_fat(first_block:int, simfat:list[list[int|str]]): + """通过首块从fat中查找FAT表""" + block_nums = [] # 创建一个空列表来存储块号 + block_nums.append(first_block) + while True: + row = first_block // 10 + clown = first_block % 10 + b_num = simfat[row][clown] + if b_num != "FF": + block_nums.append(b_num) + first_block = b_num # 更新 first_block 以继续查找下一个块 + else: + break + return block_nums + + +# X5 【编程7.14】编制程序:假定文件夹信息丢失,程序会依据FAT表,重新生成文件夹。 + +fat = [[100, 50, 0, 1, 0, 0, 0, 0, 0, 0], + [79, 3, 0, 85, 0, 28, 'FF', 91, 39, 0], + [46, 69, 52, 0, 0, 0, 0, 0, 67, 0], + [0, 0, 22, 21, 87, 0, 92, 0, 84, 66], + [0, 77, 0, 0, 0, 0, 'FF', 0, 0, 0], + ['FF', 0, 18, 0, 13, 41, 34, 0, 61, 0], + [0, 11, 0, 0, 0, 99, 20, 93, 10, 16], + [0, 36, 0, 0, 0, 0, 55, 'FF', 0, 98], + [15, 0, 0, 0, 58, 88, 32, 86, 38, 0], + [0, 76, 80, 33, 0, 0, 0, 0, 65, 17]] + +def restore_folder_by_fat(fat_table:list[list]) -> list: + fat_table = copy.deepcopy(fat_table) + ls = [n for i in fat_table for n in i] + folders = [] + while "FF" in ls: + element = "FF" + folder = list() + while element in ls: + ls.remove(element) + for i in range(len(fat_table)): + for n in range(len(fat_table[0])): + if fat_table[i][n] == element: + num = i*10+n + folder.insert(0, num) + element = num + fat_table[i][n] = 0 + print(folder, len(folder), folder[0]) + folders.append(folder) + pprint(fat_table) + pprint(fat) + + return folders + + +# 编程7.15】编制程序:首先借助于操作系统磁盘读取功能或借助于专用软件,读取真实磁盘的第0个扇区形成一个文件。 +# 然后编程解析该文件的结构,即:解析0扇区内容并显示。 + + + + +if __name__ == '__main__': + # Fileblock = initialize_fileblock(6,get_unique_tag()) + + restore_folder_by_fat(fat) + + + + + + + + diff --git a/img/backgroud.png b/img/backgroud.png new file mode 100644 index 0000000..8646557 Binary files /dev/null and b/img/backgroud.png differ diff --git a/img/bg1.png b/img/bg1.png new file mode 100644 index 0000000..d1a283a Binary files /dev/null and b/img/bg1.png differ diff --git a/img/bg2.png b/img/bg2.png new file mode 100644 index 0000000..21de35f Binary files /dev/null and b/img/bg2.png differ diff --git a/img/big_background.png b/img/big_background.png new file mode 100644 index 0000000..35a0c76 Binary files /dev/null and b/img/big_background.png differ diff --git a/img/fk1.png b/img/fk1.png new file mode 100644 index 0000000..52794ac Binary files /dev/null and b/img/fk1.png differ diff --git a/img/fk11.png b/img/fk11.png new file mode 100644 index 0000000..f7a3a7c Binary files /dev/null and b/img/fk11.png differ diff --git a/img/fk2.png b/img/fk2.png new file mode 100644 index 0000000..86b4edb Binary files /dev/null and b/img/fk2.png differ diff --git a/img/fk22.png b/img/fk22.png new file mode 100644 index 0000000..22871c1 Binary files /dev/null and b/img/fk22.png differ diff --git a/img/fk3.png b/img/fk3.png new file mode 100644 index 0000000..808ea7f Binary files /dev/null and b/img/fk3.png differ diff --git a/img/fk33.png b/img/fk33.png new file mode 100644 index 0000000..168e559 Binary files /dev/null and b/img/fk33.png differ diff --git a/img/grey.eps b/img/grey.eps new file mode 100644 index 0000000..555409d --- /dev/null +++ b/img/grey.eps @@ -0,0 +1,961 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%APL_DSC_Encoding: UTF8 +%%Title: (Unknown) +%%Creator: (Unknown) +%%CreationDate: (Unknown) +%%For: (Unknown) +%%DocumentData: Clean7Bit +%%LanguageLevel: 2 +%%Pages: 1 +%%BoundingBox: 0 0 39 38 +%%EndComments +%%BeginProlog +%%BeginFile: cg-pdf.ps +%%Copyright: Copyright 2000-2004 Apple Computer Incorporated. +%%Copyright: All Rights Reserved. +currentpacking true setpacking +/cg_md 141 dict def +cg_md begin +/L3? languagelevel 3 ge def +/bd{bind def}bind def +/ld{load def}bd +/xs{exch store}bd +/xd{exch def}bd +/cmmtx matrix def +mark +/sc/setcolor +/scs/setcolorspace +/dr/defineresource +/fr/findresource +/T/true +/F/false +/d/setdash +/w/setlinewidth +/J/setlinecap +/j/setlinejoin +/M/setmiterlimit +/i/setflat +/rc/rectclip +/rf/rectfill +/rs/rectstroke +/f/fill +/f*/eofill +/sf/selectfont +/s/show +%/as/ashow +/xS/xshow +/yS/yshow +/xyS/xyshow +/S/stroke +/m/moveto +/l/lineto +/c/curveto +/h/closepath +/n/newpath +/q/gsave +/Q/grestore +counttomark 2 idiv +%dup (number of ld's = )print == flush % *** how many +{ld}repeat pop +/SC{ % CSname + /ColorSpace fr scs +}bd +/sopr /setoverprint where{pop/setoverprint}{/pop}ifelse ld +/soprm /setoverprintmode where{pop/setoverprintmode}{/pop}ifelse ld +/cgmtx matrix def +/sdmtx{cgmtx currentmatrix pop}bd +/CM {cgmtx setmatrix}bd % pop the ctm: our gstate ctm on host is now identity +/cm {cmmtx astore CM concat}bd % reset the matrix and then concat +/W{clip newpath}bd +/W*{eoclip newpath}bd + +statusdict begin product end dup (HP) anchorsearch{ + pop pop pop % pop off the search results + true +}{ + pop % previous search result + (hp) anchorsearch{ + pop pop true + }{ + pop false + }ifelse +}ifelse + +{ % HP is the product: we use this method of stroking because of a bug in their clone printers with certain T3 fonts + { + { % charCode Wx Wy + pop pop % charCode + (0)dup 0 4 -1 roll put + F charpath + }cshow + } +}{ + {F charpath} +}ifelse +/cply exch bd +/cps {cply stroke}bd +/pgsave 0 def +/bp{/pgsave save store}bd +/ep{pgsave restore showpage}def % dont' bind +/re{4 2 roll m 1 index 0 rlineto 0 exch rlineto neg 0 rlineto h}bd + +/scrdict 10 dict def +/scrmtx matrix def +/patarray 0 def +/createpat{patarray 3 1 roll put}bd +/makepat{ +scrmtx astore pop +gsave +initgraphics +CM +patarray exch get +scrmtx +makepattern +grestore +setpattern +}bd + +/cg_BeginEPSF{ + userdict save/cg_b4_Inc_state exch put + userdict/cg_endepsf/cg_EndEPSF load put + count userdict/cg_op_count 3 -1 roll put + countdictstack dup array dictstack userdict/cg_dict_array 3 -1 roll put + 3 sub{end}repeat + /showpage {} def + 0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin + 10 setmiterlimit [] 0 setdash newpath + false setstrokeadjust false setoverprint % don't use F +}bd +/cg_EndEPSF{ + countdictstack 3 sub { end } repeat + cg_dict_array 3 1 index length 3 sub getinterval + {begin}forall + count userdict/cg_op_count get sub{pop}repeat + userdict/cg_b4_Inc_state get restore + F setpacking +}bd + +/cg_biproc{currentfile/RunLengthDecode filter}bd +/cg_aiproc{currentfile/ASCII85Decode filter/RunLengthDecode filter}bd +/ImageDataSource 0 def +L3?{ + /cg_mibiproc{pop pop/ImageDataSource{cg_biproc}def}bd + /cg_miaiproc{pop pop/ImageDataSource{cg_aiproc}def}bd +}{ + /ImageBandMask 0 def + /ImageBandData 0 def + /cg_mibiproc{ + string/ImageBandMask xs + string/ImageBandData xs + /ImageDataSource{[currentfile/RunLengthDecode filter dup ImageBandMask/readstring cvx + /pop cvx dup ImageBandData/readstring cvx/pop cvx]cvx bind}bd + }bd + /cg_miaiproc{ + string/ImageBandMask xs + string/ImageBandData xs + /ImageDataSource{[currentfile/ASCII85Decode filter/RunLengthDecode filter + dup ImageBandMask/readstring cvx + /pop cvx dup ImageBandData/readstring cvx/pop cvx]cvx bind}bd + }bd +}ifelse +/imsave 0 def +/BI{save/imsave xd mark}bd +/EI{imsave restore}bd +/ID{ +counttomark 2 idiv +dup 2 add % leave room for imagetype and imagematrix +dict begin +{def} repeat +pop % remove mark +/ImageType 1 def +/ImageMatrix[Width 0 0 Height neg 0 Height]def +currentdict dup/ImageMask known{ImageMask}{F}ifelse exch +% currentdict on stack +L3?{ + dup/MaskedImage known + { + pop + << + /ImageType 3 + /InterleaveType 2 + /DataDict currentdict + /MaskDict + << /ImageType 1 + /Width Width + /Height Height + /ImageMatrix ImageMatrix + /BitsPerComponent 1 + /Decode [0 1] + currentdict/Interpolate known + {/Interpolate Interpolate}if + >> + >> + }if +}if +exch +{imagemask}{image}ifelse +end % pop imagedict from dict stack +}bd + +/cguidfix{statusdict begin mark version end +{cvr}stopped{cleartomark 0}{exch pop}ifelse +2012 lt{dup findfont dup length dict begin +{1 index/FID ne 2 index/UniqueID ne and +{def} {pop pop} ifelse}forall +currentdict end definefont pop +}{pop}ifelse +}bd +/t_array 0 def +/t_i 0 def +/t_c 1 string def +/x_proc{ % x y + exch t_array t_i get add exch moveto + /t_i t_i 1 add store +}bd +/y_proc{ % x y + t_array t_i get add moveto + /t_i t_i 1 add store +}bd +/xy_proc{ + % x y + t_array t_i 2 copy 1 add get 3 1 roll get + 4 -1 roll add 3 1 roll add moveto + /t_i t_i 2 add store +}bd +/sop 0 def % don't bind sop +/cp_proc/x_proc ld % default moveto proc is for xwidths only +/base_charpath % string array +{ + /t_array xs + /t_i 0 def + { % char + t_c 0 3 -1 roll put + currentpoint + t_c cply sop + cp_proc + }forall + /t_array 0 def +}bd +/sop/stroke ld % default sop is stroke. Done here so we don't bind in /base_charpath + +% default sop is stroke +/nop{}def +/xsp/base_charpath ld +/ysp{/cp_proc/y_proc ld base_charpath/cp_proc/x_proc ld}bd +/xysp{/cp_proc/xy_proc ld base_charpath/cp_proc/x_proc ld}bd +/xmp{/sop/nop ld /cp_proc/x_proc ld base_charpath/sop/stroke ld}bd +/ymp{/sop/nop ld /cp_proc/y_proc ld base_charpath/sop/stroke ld}bd +/xymp{/sop/nop ld /cp_proc/xy_proc ld base_charpath/sop/stroke ld}bd +/refnt{ % newname encoding fontname +findfont dup length dict copy dup +/Encoding 4 -1 roll put +definefont pop +}bd +/renmfont{ % newname fontname +findfont dup length dict copy definefont pop +}bd + +L3? dup dup{save exch}if + +% languagelevel2 ONLY code goes here + +/Range 0 def +/DataSource 0 def +/val 0 def +/nRange 0 def +/mulRange 0 def +/d0 0 def +/r0 0 def +/di 0 def +/ri 0 def +/a0 0 def +/a1 0 def +/r1 0 def +/r2 0 def +/dx 0 def +/Nsteps 0 def +/sh3tp 0 def +/ymax 0 def +/ymin 0 def +/xmax 0 def +/xmin 0 def + +/setupFunEval % funDict -- % this calculates and sets up a function dict for evaulation. +{ + begin + /nRange Range length 2 idiv store + /mulRange % precompute the range data needed to map a sample value from the table to a range value + % this data looks like [ range0mul range0min range1mul range1min ... rangeN-1mul rangeN-1min ] + [ + 0 1 nRange 1 sub + { % index + 2 mul/nDim2 xd % 2*dimension# we are dealing with + Range nDim2 get % ymin + Range nDim2 1 add get % ymin ymax + 1 index sub % ymin (ymax-ymin) + % xmin = 0, xmax = 255 (2^bitspersample - 1) + 255 div % ymin (ymax-ymin)/(xmax - xmin) + exch % (ymax-ymin)/(xmax - xmin) ymin + }for + ]store + end +}bd + +/FunEval % val1 fundict -> comp1 comp2 ... compN +{ + begin + % the value passed in is the base index into the table + nRange mul /val xd % compute the actual index to the table + % since there are nRange entries per base index + 0 1 nRange 1 sub + { + dup 2 mul/nDim2 xd % dim + val % base value to use to do our lookup + add DataSource exch get % lookedupval + mulRange nDim2 get mul % lookedupval*(ymax-ymin)/(xmax-xmin) + mulRange nDim2 1 add get % lookedupval*(ymax-ymin)/(xmax-xmin) ymin + add % interpolated result + }for % comp1 comp2 ... compN + end +}bd + +/max % a b -> max(a, b) +{ + 2 copy lt + {exch pop}{pop}ifelse +}bd + +/sh2 +{ % emulation of shading type 2. Assumes shading dictionary is top dictionary on the dict stack + /Coords load aload pop % x0 y0 x1 y1 + 3 index 3 index translate % origin is now at beginning point of shading + % x0 y0 x1 y1 + 3 -1 roll sub % x0 x1 y1-y0 + 3 1 roll exch % y1-y0 x1 x0 + sub % y1-y0 x1-x0 + 2 copy + dup mul exch dup mul add sqrt % length of segment between two points + dup + scale + atan % atan (dy/dx) + %dup (rotation angle = )print == + rotate % now line between 0,0 and 1,0 is the line perpendicular to which the axial lines are drawn + + /Function load setupFunEval % may need to setup function dictionary by calling setupFunEval + + % this is now specific to axial shadings. Compute the maximum bounds to fill + clippath {pathbbox}stopped {0 0 0 0}if newpath % x0 y0 x1 y1 + /ymax xs + /xmax xs + /ymin xs + /xmin xs + currentdict/Extend known + { + /Extend load 0 get + { + 0/Function load FunEval sc % evaluate the function to get a color and set it + xmin ymin xmin abs ymax ymin sub rectfill + }if + }if + % paint the rects. The sampling frequency is that of our table + /Nsteps/Function load/Size get 0 get 1 sub store + /dx 1 Nsteps div store + gsave + /di ymax ymin sub store + /Function load + % loop Nsteps + 1 times, incrementing the index by 1 each time + 0 1 Nsteps + { + 1 index FunEval sc + 0 ymin dx di rectfill + dx 0 translate + }for + pop % pop our function + grestore % origin is back to start point + currentdict/Extend known + { + /Extend load 1 get + { + Nsteps/Function load FunEval sc % last element + 1 ymin xmax 1 sub abs ymax ymin sub rectfill + }if + }if +}bd + +/shp % this paints our shape for shading type 3 +{ % x1 r1 x0 r0 - + 4 copy + + % fill interior arc + dup 0 gt{ + 0 exch a1 a0 arc + }{ + pop 0 moveto + }ifelse + + dup 0 gt{ + 0 exch a0 a1 arcn + }{ + pop 0 lineto + }ifelse + + fill + + % fill exterior arc + dup 0 gt{ + 0 exch a0 a1 arc + }{ + pop 0 moveto + }ifelse + + dup 0 gt{ + 0 exch a1 a0 arcn + }{ + pop 0 lineto + }ifelse + + fill +}bd + +/calcmaxs +{ % calculate maximum distance vector from origin to corner points + % of bbox + xmin dup mul ymin dup mul add sqrt % (xmin2 + ymin2) + xmax dup mul ymin dup mul add sqrt % (xmax2 + ymin2) + xmin dup mul ymax dup mul add sqrt % (xmin2 + ymax2) + xmax dup mul ymax dup mul add sqrt % (xmax2 + ymax2) + max max max % maximum value +}bd + +/sh3 +{ % emulation of shading type 3. Assumes shading dictionary is top dictionary on the dict stack + /Coords load aload pop % x0 y0 r1 x1 y1 r2 + 5 index 5 index translate % origin is now at first circle origin + 3 -1 roll 6 -1 roll sub % y0 r1 y1 r2 dx + 3 -1 roll 5 -1 roll sub % r1 r2 dx dy + 2 copy dup mul exch dup mul add sqrt + /dx xs % r1 r2 dx dy + 2 copy 0 ne exch 0 ne or + { + % r1 r2 dx dy + exch atan rotate % we are now rotated so dy is zero and positive values of dx move us as expected + }{ + pop pop + }ifelse + % r1 r2 + /r2 xs + /r1 xs + /Function load + dup/Size get 0 get 1 sub % this is the size of our table minus 1 + /Nsteps xs % at some point we should optimize this better so NSteps is based on needed steps for the device + setupFunEval % may need to setup function dictionary by calling setupFunEval + % determine the case: + % case 0: circle1 inside circle2 + % case 1: circle 2 inside circle 1 + % case 2: r1 = r2 + % case 3: r1 != r2 + dx r2 add r1 lt{ + % circle 2 inside of circle 1 + 0 + }{ + dx r1 add r2 le + { % circle 1 inside of circle 2 + 1 + }{ % circles don't contain each other + r1 r2 eq + { % equal + 2 + }{ % r1 != r2 + 3 + }ifelse + }ifelse + }ifelse + /sh3tp xs % sh3tp has the number of our different cases + clippath {pathbbox}stopped {0 0 0 0}if + newpath % x0 y0 x1 y1 + /ymax xs + /xmax xs + /ymin xs + /xmin xs + + % Arc angle atan( sqrt((dx*dx + dy*dy) - dr*dr), dr) + dx dup mul r2 r1 sub dup mul sub dup 0 gt + { + sqrt r2 r1 sub atan + /a0 exch 180 exch sub store + /a1 a0 neg store + }{ + pop + /a0 0 store + /a1 360 store + }ifelse + + currentdict/Extend known + { + /Extend load 0 get r1 0 gt and % no need to extend if the radius of the first end is 0 + { + 0/Function load FunEval sc % evaluate the function to get a color and set it + % case 0: circle1 inside circle2 + % case 1: circle 2 inside circle 1 + % case 2: circles don't contain each other and r1 == r2 + % case 3: circles don't contain each other and r1 != r2 + { + { % case 0 + dx 0 r1 360 0 arcn + xmin ymin moveto + xmax ymin lineto + xmax ymax lineto + xmin ymax lineto + xmin ymin lineto + eofill % for the bigger radius we fill everything except our circle + } + { % case 1 + r1 0 gt{0 0 r1 0 360 arc fill}if + } + { % case 2 + % r1 == r2, extend 0 + % r3 = r, x3 = -(abs(minx) + r), x1 = 0 + + % x(i+1) r(i+1) x(i) r(i) shp + 0 r1 xmin abs r1 add neg r1 shp + } + { % case 3 + % no containment, r1 != r2 + + r2 r1 gt{ % the endpoint we are drawing is that with a circle of zero radius + % x(i+1) r(i+1) x(i) r(i) shp + 0 r1 + r1 neg r2 r1 sub div dx mul % this is point of beginning circle + 0 % point of ending circle + shp % takes x(i+1) r(i+1) x(i) r(i) + }{ % the first circle is the bigger of the two + % we find a circle on our line which is outside the bbox in the + % negative direction + % x(i+1) r(i+1) x(i) r(i) shp + 0 r1 calcmaxs % 0 r1 maxs + dup + % calculating xs: (-(maxs+r2)*x2)/(x2-(r1-r2)) + r2 add dx mul dx r1 r2 sub sub div + neg % maxs xs' + exch 1 index % xs' maxs xs' + abs exch sub + shp + }ifelse + } + }sh3tp get exec % execute the extend at beginning proc for our shading type + }if + }if + + % now do the shading + /d0 0 store + /r0 r1 store + /di dx Nsteps div store + /ri r2 r1 sub Nsteps div store + /Function load + 0 1 Nsteps + { % function t(i) + 1 index FunEval sc + d0 di add r0 ri add d0 r0 shp + { + % fill interior arc + d0 0 r0 a1 a0 arc + d0 di add 0 r0 ri add a0 a1 arcn + fill + + % fill exterior arc + d0 0 r0 a0 a1 arc + d0 di add 0 r0 ri add a1 a0 arcn + fill + }pop + + % advance to next + /d0 d0 di add store + /r0 r0 ri add store + }for + pop % pop our function dict + + % handle Extend + currentdict/Extend known + { + /Extend load 1 get r2 0 gt and % no need to extend if the radius of the last end is 0 + { + Nsteps/Function load FunEval sc % last element + % case 0: circle1 inside circle2 + % case 1: circle 2 inside circle 1 + % case 2: circles don't contain each other and r1 == r2 + % case 3: circles don't contain each other and r1 != r2 + { + { + dx 0 r2 0 360 arc fill + } + { + dx 0 r2 360 0 arcn + xmin ymin moveto + xmax ymin lineto + xmax ymax lineto + xmin ymax lineto + xmin ymin lineto + eofill % for the bigger radius we fill everything except our circle + } + { % r1 == r2, extend 1 + % r3 = r, x3 = (abs(xmax) + r), x1 = dx + % x(i+1) r(i+1) x(i) r(i) shp + xmax abs r1 add r1 dx r1 shp + } + { % no containment, r1 != r2 + + r2 r1 gt{ + % we find a circle on our line which is outside the bbox in the + % positive direction + % x(i+1) r(i+1) x(i) r(i) shp + calcmaxs dup % maxs maxs + % calculating xs: ((maxs+r1)*x2)/(x2-(r2-r1)) + r1 add dx mul dx r2 r1 sub sub div % maxs xs + exch 1 index % xs maxs xs + exch sub + dx r2 + shp + }{ % the endpoint we are drawing is that with a circle of zero radius + % x(i+1) r(i+1) x(i) r(i) shp + r1 neg r2 r1 sub div dx mul % this is point of ending circle + 0 % radius of ending circle + dx % point of starting circle + r2 % radius of starting circle + shp + }ifelse + } + } + sh3tp get exec % execute the extend at end proc for our shading type + }if + }if +}bd +/sh % emulation of shfill operator for type 2 and type 3 shadings based on type 0 functions +{ % shadingDict -- + begin + /ShadingType load dup dup 2 eq exch 3 eq or + { % shadingtype + gsave + newpath + /ColorSpace load scs + currentdict/BBox known + { + /BBox load aload pop % llx lly urx ury + 2 index sub % llx lly urx ury-lly + 3 index % llx lly urx ury-lly llx + 3 -1 roll exch sub + exch rectclip + }if + 2 eq + {sh2}{sh3}ifelse + grestore + }{ + % shadingtype + pop + (DEBUG: shading type unimplemented\n)print flush + }ifelse + end +}bd + +% end of language level 2 ONLY code + +{restore}if not dup{save exch}if +% languagelevel3 ONLY code goes here + L3?{ % we do these loads conditionally or else they will fail on a level 2 printer + /sh/shfill ld + /csq/clipsave ld + /csQ/cliprestore ld + }if +{restore}if + +%currentdict dup maxlength exch length sub (number of extra slots in md = )print == flush % *** how many entries are free +end +setpacking +% count 0 ne { pstack(***extras on stack during prolog execution***\n)print flush}if % *** BARK if anything is left on stack +%%EndFile +%%EndProlog +%%BeginSetup +%%EndSetup +%%Page: 1 1 +%%PageBoundingBox: 0 0 39 38 +%%BeginPageSetup +cg_md begin +bp +sdmtx +[ /CIEBasedABC 4 dict dup begin +/WhitePoint [ 0.9505 1.0000 1.0891 ] def +/DecodeABC [ +{ 1.0 0.0 3 -1 roll 1 index 1 index le { exch pop} { pop } ifelse + 1 index 1 index ge { exch pop } { pop } ifelse < +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000001010101010101010101010101 +0101010101010101010101010101010101010101010101020202020202020202 +0202020202020202020202020202020202030303030303030303030303030303 +0303030303030304040404040404040404040404040404040404050505050505 +0505050505050505050506060606060606060606060606060607070707070707 +0707070707070708080808080808080808080808090909090909090909090909 +0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c +0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f10101010 +1010101010111111111111111112121212121212121313131313131313141414 +1414141414151515151515151616161616161616171717171717171818181818 +18181919191919191a1a1a1a1a1a1a1b1b1b1b1b1b1c1c1c1c1c1c1c1d1d1d1d +1d1d1e1e1e1e1e1e1f1f1f1f1f1f202020202020212121212121222222222223 +2323232323242424242425252525252526262626262727272727282828282829 +292929292a2a2a2a2a2b2b2b2b2b2c2c2c2c2c2d2d2d2d2d2e2e2e2e2e2f2f2f +2f2f303030303131313131323232323333333333343434343535353535363636 +36373737373838383839393939393a3a3a3a3b3b3b3b3c3c3c3c3d3d3d3d3e3e +3e3e3f3f3f3f4040404041414141424242424343434444444445454545464646 +4647474748484848494949494a4a4a4b4b4b4b4c4c4c4d4d4d4d4e4e4e4f4f4f +4f50505051515151525252535353535454545555555656565657575758585859 +59595a5a5a5a5b5b5b5c5c5c5d5d5d5e5e5e5f5f5f6060606061616162626263 +63636464646565656666666767676868686969696a6a6a6b6b6b6c6c6d6d6d6e +6e6e6f6f6f707070717171727273737374747475757576767677777878787979 +797a7a7b7b7b7c7c7c7d7d7e7e7e7f7f7f808081818182828283838484848585 +86868687878888888989898a8a8b8b8b8c8c8d8d8d8e8e8f8f90909091919292 +9293939494949595969697979798989999999a9a9b9b9c9c9c9d9d9e9e9f9f9f +a0a0a1a1a2a2a3a3a3a4a4a5a5a6a6a6a7a7a8a8a9a9aaaaabababacacadadae +aeafafb0b0b0b1b1b2b2b3b3b4b4b5b5b6b6b6b7b7b8b8b9b9bababbbbbcbcbd +bdbebebebfbfc0c0c1c1c2c2c3c3c4c4c5c5c6c6c7c7c8c8c9c9cacacbcbcccc +cdcdcececfcfd0d0d1d1d2d2d3d3d4d4d5d5d6d6d7d7d8d8d9d9dadadbdcdcdd +dddededfdfe0e0e1e1e2e2e3e3e4e4e5e6e6e7e7e8e8e9e9eaeaebebecededee +eeefeff0f0f1f1f2f3f3f4f4f5f5f6f6f7f8f8f9f9fafafbfcfcfdfdfefeffff +> dup length 1 sub 3 -1 roll mul dup dup floor cvi exch ceiling + cvi 3 index exch get 4 -1 roll 3 -1 roll get + dup 3 1 roll sub 3 -1 roll dup floor cvi sub mul add 255 div } bind + +{ 1.0 0.0 3 -1 roll 1 index 1 index le { exch pop} { pop } ifelse + 1 index 1 index ge { exch pop } { pop } ifelse < +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000001010101010101010101010101 +0101010101010101010101010101010101010101010101020202020202020202 +0202020202020202020202020202020202030303030303030303030303030303 +0303030303030304040404040404040404040404040404040404050505050505 +0505050505050505050506060606060606060606060606060607070707070707 +0707070707070708080808080808080808080808090909090909090909090909 +0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c +0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f10101010 +1010101010111111111111111112121212121212121313131313131313141414 +1414141414151515151515151616161616161616171717171717171818181818 +18181919191919191a1a1a1a1a1a1a1b1b1b1b1b1b1c1c1c1c1c1c1c1d1d1d1d +1d1d1e1e1e1e1e1e1f1f1f1f1f1f202020202020212121212121222222222223 +2323232323242424242425252525252526262626262727272727282828282829 +292929292a2a2a2a2a2b2b2b2b2b2c2c2c2c2c2d2d2d2d2d2e2e2e2e2e2f2f2f +2f2f303030303131313131323232323333333333343434343535353535363636 +36373737373838383839393939393a3a3a3a3b3b3b3b3c3c3c3c3d3d3d3d3e3e +3e3e3f3f3f3f4040404041414141424242424343434444444445454545464646 +4647474748484848494949494a4a4a4b4b4b4b4c4c4c4d4d4d4d4e4e4e4f4f4f +4f50505051515151525252535353535454545555555656565657575758585859 +59595a5a5a5a5b5b5b5c5c5c5d5d5d5e5e5e5f5f5f6060606061616162626263 +63636464646565656666666767676868686969696a6a6a6b6b6b6c6c6d6d6d6e +6e6e6f6f6f707070717171727273737374747475757576767677777878787979 +797a7a7b7b7b7c7c7c7d7d7e7e7e7f7f7f808081818182828283838484848585 +86868687878888888989898a8a8b8b8b8c8c8d8d8d8e8e8f8f90909091919292 +9293939494949595969697979798989999999a9a9b9b9c9c9c9d9d9e9e9f9f9f +a0a0a1a1a2a2a3a3a3a4a4a5a5a6a6a6a7a7a8a8a9a9aaaaabababacacadadae +aeafafb0b0b0b1b1b2b2b3b3b4b4b5b5b6b6b6b7b7b8b8b9b9bababbbbbcbcbd +bdbebebebfbfc0c0c1c1c2c2c3c3c4c4c5c5c6c6c7c7c8c8c9c9cacacbcbcccc +cdcdcececfcfd0d0d1d1d2d2d3d3d4d4d5d5d6d6d7d7d8d8d9d9dadadbdcdcdd +dddededfdfe0e0e1e1e2e2e3e3e4e4e5e6e6e7e7e8e8e9e9eaeaebebecededee +eeefeff0f0f1f1f2f3f3f4f4f5f5f6f6f7f8f8f9f9fafafbfcfcfdfdfefeffff +> dup length 1 sub 3 -1 roll mul dup dup floor cvi exch ceiling + cvi 3 index exch get 4 -1 roll 3 -1 roll get + dup 3 1 roll sub 3 -1 roll dup floor cvi sub mul add 255 div } bind + +{ 1.0 0.0 3 -1 roll 1 index 1 index le { exch pop} { pop } ifelse + 1 index 1 index ge { exch pop } { pop } ifelse < +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000001010101010101010101010101 +0101010101010101010101010101010101010101010101020202020202020202 +0202020202020202020202020202020202030303030303030303030303030303 +0303030303030304040404040404040404040404040404040404050505050505 +0505050505050505050506060606060606060606060606060607070707070707 +0707070707070708080808080808080808080808090909090909090909090909 +0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c +0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f10101010 +1010101010111111111111111112121212121212121313131313131313141414 +1414141414151515151515151616161616161616171717171717171818181818 +18181919191919191a1a1a1a1a1a1a1b1b1b1b1b1b1c1c1c1c1c1c1c1d1d1d1d +1d1d1e1e1e1e1e1e1f1f1f1f1f1f202020202020212121212121222222222223 +2323232323242424242425252525252526262626262727272727282828282829 +292929292a2a2a2a2a2b2b2b2b2b2c2c2c2c2c2d2d2d2d2d2e2e2e2e2e2f2f2f +2f2f303030303131313131323232323333333333343434343535353535363636 +36373737373838383839393939393a3a3a3a3b3b3b3b3c3c3c3c3d3d3d3d3e3e +3e3e3f3f3f3f4040404041414141424242424343434444444445454545464646 +4647474748484848494949494a4a4a4b4b4b4b4c4c4c4d4d4d4d4e4e4e4f4f4f +4f50505051515151525252535353535454545555555656565657575758585859 +59595a5a5a5a5b5b5b5c5c5c5d5d5d5e5e5e5f5f5f6060606061616162626263 +63636464646565656666666767676868686969696a6a6a6b6b6b6c6c6d6d6d6e +6e6e6f6f6f707070717171727273737374747475757576767677777878787979 +797a7a7b7b7b7c7c7c7d7d7e7e7e7f7f7f808081818182828283838484848585 +86868687878888888989898a8a8b8b8b8c8c8d8d8d8e8e8f8f90909091919292 +9293939494949595969697979798989999999a9a9b9b9c9c9c9d9d9e9e9f9f9f +a0a0a1a1a2a2a3a3a3a4a4a5a5a6a6a6a7a7a8a8a9a9aaaaabababacacadadae +aeafafb0b0b0b1b1b2b2b3b3b4b4b5b5b6b6b6b7b7b8b8b9b9bababbbbbcbcbd +bdbebebebfbfc0c0c1c1c2c2c3c3c4c4c5c5c6c6c7c7c8c8c9c9cacacbcbcccc +cdcdcececfcfd0d0d1d1d2d2d3d3d4d4d5d5d6d6d7d7d8d8d9d9dadadbdcdcdd +dddededfdfe0e0e1e1e2e2e3e3e4e4e5e6e6e7e7e8e8e9e9eaeaebebecededee +eeefeff0f0f1f1f2f3f3f4f4f5f5f6f6f7f8f8f9f9fafafbfcfcfdfdfefeffff +> dup length 1 sub 3 -1 roll mul dup dup floor cvi exch ceiling + cvi 3 index exch get 4 -1 roll 3 -1 roll get + dup 3 1 roll sub 3 -1 roll dup floor cvi sub mul add 255 div } bind +] def +/MatrixABC [ 0.4124 0.2126 0.0193 0.3576 0.7151 0.1192 0.1805 0.0722 0.9508 ] def +/RangeLMN [ 0.0 0.9505 0.0 1.0000 0.0 1.0891 ] def +end ] /Cs1 exch/ColorSpace dr pop +%%EndPageSetup +0.60000002 i +/Cs1 SC +0.59215689 0.59215689 0.59215689 sc +q +0 25.643332 m +25.422678 25.643332 l +25.422678 0.22065477 l +0 0.22065477 l +0 25.643332 l +h +W* +0 0 39 38 rc +0 25.643332 m +25.422678 25.643332 l +25.422678 0.22065477 l +0 0.22065477 l +0 25.643332 l +h +f +Q +2.0678732 w +0.40000001 0.40000001 0.40000001 sc +q +0 25.643332 m +25.422678 25.643332 l +25.422678 0.22065477 l +0 0.22065477 l +0 25.643332 l +h +W* +0 0 39 38 rc +1 0 0 -1 0 25.643332 cm +0 0 m +25.422678 0 l +25.422678 25.422678 l +0 25.422678 l +0 0 l +h +S +Q +q +0 0 39 38 rc +40 0 0 13 -1 25 cm +save +360 15 cg_miaiproc +0 -39 -39{ +gsave 1 120 div 1 39 div scale 0 exch translate +currentfile 0 (EOD +)/SubFileDecode filter +L3?{flushfile}{cvx exec}ifelse +120 40 scale +BI +/Width 120 +/Height 40 +/BitsPerComponent 8 +/Decode[ +0 1 +0 1 +0 1 +] +/DataSource ImageDataSource +/MaskedImage true +ID +EI +grestore} bind for +0 39 m 0 0 l 120 0 l 120 39 l h W n EOD +JcC<$MZ<5IL];r*PQ11Rrr7QLJcD8?nc4OHrpB]]o;$r5Z)%B%rqlTmnc8%VU&Y,QrcWj)k@VD>rdXoe +rqQBjnc4aNrnIEkgLc"Ka_(O+rb_XHrqQBjnc7DD\c;ZVrbM:@rd03FgOA44rd"0Kre^Vfqe#j&qu?3e +Q2gj&rb21@rb2:fc^03LnrqQJSph'MFrf_o"^6ehTrb)+?rb2:fq.9V=rbh^uj-Tb0ph'O#qu?3eaT)82reC2[rcJ.)R$X_; +re1&YrbVRfph'MFrfc9,rfm1irqQBjnc6l5rpB]5rFYt>rcnF.JX=*;rdjiVrc%jfph'MIrfuu>m[*p; +ph'O#qu?3ecN!n)rc\'Krd99`rKk9crdFQRrcS3eph'MMrg)9)rfm1irqQBjnc7);rnIEkph'MVnX"fn +cBnNrrd"9Nrd+Qdph'MPrg)3'!13\Lph'O#qu?3eeGoNqrbM:@re5oijd4\frg!J*ph'MTrc7dGrdW=^ +rfm1irqQBjnc7;Arl"eLqe#h@re]McrfmD&ph'MYrbhLCre&L_rfm1irqHNos8Dug!8@JP\+jS7 +C&X'BQd(lfQi<0IDtmrDM#M/dB)ZHBLWc%`Pk\kiq"t*^!8[\SWVC*)C]9C2Q[tM&Qi<*GD>7`BMuIDe +B)ZKCMTD.`Pk\kiq"t*_!!!#Zs8MrqSG6^qDZ5cLQbJgcNrEhnB)?3>N;.#aCAs43Qi<6EB)_T&s7-0P +s8MfmOSEGeEW20$Q^4!;MuIGfB)ZHBN;.#aD#TL4Qi<6EB)_T&s7-0Zs8)cpoDXL>B)ZoOQ%>:9Qi;g? +BDZa>JX*j4rdjiVrc%jfph'MIrfu`7d?jisph'O#qu?3eo)J^Drc!F#l=RV>rcJ-e +ph'MLrg(!Zrfm1irqQBjnc8@_rmC^\hI_=N`b,3qrce-Lrd4X1d?im[rfm1irqQBjnc8Ibrl"eLJS*>B +dUrK-rc7dGrdV&:rfm1irqQBjnc8Ib_eF[9gM-Y>ph'MX[[6ZRrfm1irqQBjnc8IbJS)K*jC\CCqe#hW +VjICIph'O#qu;0 +~> 0 40 m 0 39 l 120 39 l 120 40 l h W n EOD +nc8IbJS(Hbrdk,^r+>qXVjICIph'O#JcG<@JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$ +JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$ +JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$ +JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcG!7 +J, +~> restore +14 0 0 25 25 0 cm +save +126 6 cg_miaiproc +38 -37 -36{ +gsave 1 42 div 1 75 div scale 0 exch translate +currentfile 0 (EOD +)/SubFileDecode filter +L3?{flushfile}{cvx exec}ifelse +42 38 scale +BI +/Width 42 +/Height 38 +/BitsPerComponent 8 +/Decode[ +0 1 +0 1 +0 1 +] +/DataSource ImageDataSource +/MaskedImage true +ID +EI +grestore} bind for +0 37 m 0 0 l 42 0 l 42 37 l h W n EOD +JcG]KqZ-V-rdt#Zre.29rfm1i!;HTiq"t*g!<-U0K)90ZKVt19Pk\kiq"t*g!<-U0K)90ZKVt19PQ>B. +qI]a%qu?Nnrau.]qe#h\VjICIph'O#qu?Nnrau.]qe#h\WgE^Orfm1irqQBjqZ-V-rdt#Zre.29rfm1i +rqQBjqZ-V-rdt#Zre.SDp6YcCph'O#qu?Nnrau.]qe#h\VjICIph'O#qu?Nnrau.]qe#h\\sMiOrfm1i +rqQBjqZ-V-rdt#Zre.29rfm1irqQBjqZ-V-rdt#Zre/.Tk*Q(3ph'O#qu?Nnrau.]qe#h\VjICIph'O# +qu?Nnrau.]qe#h\b*UtOrfm1irqQBjqZ-V-rdt#Zre.29rfm1irqQBjqZ-V-rdt#Zre/^desHB#ph'O# +qu?Nnrau.]qe#h\VjICIph'O#qu?Nnrau.]qe#h\g6^*Orfm1irqQBjqZ-V-rdt#Zre.29rfm1irqQBj +qZ-V-rdt#Zre09t`g?[hph'O#qu?Nnrau.]qe#h\VjICIph'O#qu?Nnrau.]qe#h\lBf5Orfm1irqQBj +qZ-V-rdt#Zre.29rfm1irqQBjqZ-V-rdt#Zre0j/[[6uXph'O#qu?Nnrau.]qe#h\VjICIph'O#qu?Nn +rau.]qe#h\qNn@Orfm1irqQBjqZ-V-rdt#Zre.29rfm1irqQBjqZ-V-rdt#Z!JH++KVt19Pk\kiq"t*g +!<-U0K)90ZKVt19Pk\kiq"t*g!<-U0K)90ZKVt19Pk\kiq"t*g!<-U0K)90ZKVt19Pk\kiq"t*i!!*'" +rau.]qe#h\VjICIph'O#qu?Nnrau.]qe#h\VjICIph'O#!WW2us8)fqB)[DZB)[I]Qi<6EB)_T&s8)fq +B)[DZB)[I]Qi<6HB)ZEAq"t*g!<-U0K)90ZKVt19Pk\kiq"t*g!<-U0K)90ZKVt.:PQ@#5ph'O#qu?Nn +rau.]qe#h\VjICIph'O#qu;0 +~> 0 38 m 0 0 l 42 0 l 42 38 l h W n EOD +qZ-V-rdt#Zre.29rfm1irqQBjqZ-V-rdt#Zre.29rfm1i!;HTiq"t*g!<-U0K)90ZKVt19Pk\kiq"t*g +!<-U0K)90ZKVt19P6#9-qI]a%qu?Nnrau.]qe#h\WgE^Lrc@jHrqQBjqZ-V-rdt#Zre.D?rfR1tph'Me +rr2fpqZ-V-rdt#Zre.MBrf6tnph'N!rr)WlqZ-V-rdt#Zre.VE!/U`5M>h2`B)].-s8)fqB)[DZB)[Il +Qi;[5B)ZND`p`s)!<-U0K)90ZKY!KMQi;I/B)Z`JfBiP7!<-U0K)90ZKYNlQQMu.(B)[#RjQZ^A!<-U0 +K)90ZKYj)TPl>b!B)[D]n)jZI!<-U0K)90ZKZ0;WOoB7nB)[nkpZ);N!<-U0K)90ZKZ]V^Q^@]3rbM:@ +rh08gi;`ZSrau.]qe#h\bEr3brb2(=rj1>YqZ-V-rdt#Zre/^drKmM:ph'M>rl3RiqZ-V-rdt#Zre/[c +rdOWSrbqeeeGoCGrau.]qe#h\g6_f*rg*P.ph'MLroDK,qZ-V-rdt#Zre0!lrfmD'ph'MWrpS/4qZ-V- +rdt#Zre09tr0RDFrbqRDrf@'QbQ%G>rau.]qe#h\i0XG'rbM:@rh08gaT),;rau.]qe#h\lBh@6reg\g +ph'N2_Z0K5rau.]qe#h\k*Q(#ph'M>rl)YPqZ-V-rdt#Zre0j/pm:u/ph'MCrmna^qZ-V-rdt#Zre0a, +rg*P.ph'MLroCWiqZ-V-rdt#Zre1-7q3V)Frc@jHrdk(;[f?4)rau.]qe#h\op>Z@rbqRDrf@'QZiBn& +rau.]qdok^KE-]#Qi<$EC\VN@TDnbms8)fqB)[DZB)[J\Qi;mAB_Z3=ZE!s%!<-U0K)90ZK`7>;K_T0Y +C&Z)Ls8)fqB)[DZB)[J_Ie[OSDZ81^s8;ou!!*"1rdt#ZrbV@ArceA%U&Xuirau.]nn.lPrpQT]rVu`p +rau.]ok+2arq;i]qZ-V-rdsoWrh'2fV#U,fqZ-V-rdt#ZriqXdqZ-V-rdt,`rl(Z4mJm%`rau.crmcu- +J, +~> 0 38 m 0 36 l 42 36 l 42 38 l h W n EOD +qZ-V-reUR(N;rbTrkn`uOoL"4JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$ +JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$l2Q8 +~> restore +ep +end +%%Trailer +%%EOF diff --git a/img/jade_blue_bg.png b/img/jade_blue_bg.png new file mode 100644 index 0000000..7cf0cdf Binary files /dev/null and b/img/jade_blue_bg.png differ diff --git a/img/pink_bg.png b/img/pink_bg.png new file mode 100644 index 0000000..67b2517 Binary files /dev/null and b/img/pink_bg.png differ diff --git a/img/purple_bg.png b/img/purple_bg.png new file mode 100644 index 0000000..acd7ff5 Binary files /dev/null and b/img/purple_bg.png differ diff --git a/img/sky_blue_bg.png b/img/sky_blue_bg.png new file mode 100644 index 0000000..47abb3e Binary files /dev/null and b/img/sky_blue_bg.png differ diff --git a/img/white.eps b/img/white.eps new file mode 100644 index 0000000..168c9ca --- /dev/null +++ b/img/white.eps @@ -0,0 +1,961 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%APL_DSC_Encoding: UTF8 +%%Title: (Unknown) +%%Creator: (Unknown) +%%CreationDate: (Unknown) +%%For: (Unknown) +%%DocumentData: Clean7Bit +%%LanguageLevel: 2 +%%Pages: 1 +%%BoundingBox: 0 0 39 38 +%%EndComments +%%BeginProlog +%%BeginFile: cg-pdf.ps +%%Copyright: Copyright 2000-2004 Apple Computer Incorporated. +%%Copyright: All Rights Reserved. +currentpacking true setpacking +/cg_md 141 dict def +cg_md begin +/L3? languagelevel 3 ge def +/bd{bind def}bind def +/ld{load def}bd +/xs{exch store}bd +/xd{exch def}bd +/cmmtx matrix def +mark +/sc/setcolor +/scs/setcolorspace +/dr/defineresource +/fr/findresource +/T/true +/F/false +/d/setdash +/w/setlinewidth +/J/setlinecap +/j/setlinejoin +/M/setmiterlimit +/i/setflat +/rc/rectclip +/rf/rectfill +/rs/rectstroke +/f/fill +/f*/eofill +/sf/selectfont +/s/show +%/as/ashow +/xS/xshow +/yS/yshow +/xyS/xyshow +/S/stroke +/m/moveto +/l/lineto +/c/curveto +/h/closepath +/n/newpath +/q/gsave +/Q/grestore +counttomark 2 idiv +%dup (number of ld's = )print == flush % *** how many +{ld}repeat pop +/SC{ % CSname + /ColorSpace fr scs +}bd +/sopr /setoverprint where{pop/setoverprint}{/pop}ifelse ld +/soprm /setoverprintmode where{pop/setoverprintmode}{/pop}ifelse ld +/cgmtx matrix def +/sdmtx{cgmtx currentmatrix pop}bd +/CM {cgmtx setmatrix}bd % pop the ctm: our gstate ctm on host is now identity +/cm {cmmtx astore CM concat}bd % reset the matrix and then concat +/W{clip newpath}bd +/W*{eoclip newpath}bd + +statusdict begin product end dup (HP) anchorsearch{ + pop pop pop % pop off the search results + true +}{ + pop % previous search result + (hp) anchorsearch{ + pop pop true + }{ + pop false + }ifelse +}ifelse + +{ % HP is the product: we use this method of stroking because of a bug in their clone printers with certain T3 fonts + { + { % charCode Wx Wy + pop pop % charCode + (0)dup 0 4 -1 roll put + F charpath + }cshow + } +}{ + {F charpath} +}ifelse +/cply exch bd +/cps {cply stroke}bd +/pgsave 0 def +/bp{/pgsave save store}bd +/ep{pgsave restore showpage}def % dont' bind +/re{4 2 roll m 1 index 0 rlineto 0 exch rlineto neg 0 rlineto h}bd + +/scrdict 10 dict def +/scrmtx matrix def +/patarray 0 def +/createpat{patarray 3 1 roll put}bd +/makepat{ +scrmtx astore pop +gsave +initgraphics +CM +patarray exch get +scrmtx +makepattern +grestore +setpattern +}bd + +/cg_BeginEPSF{ + userdict save/cg_b4_Inc_state exch put + userdict/cg_endepsf/cg_EndEPSF load put + count userdict/cg_op_count 3 -1 roll put + countdictstack dup array dictstack userdict/cg_dict_array 3 -1 roll put + 3 sub{end}repeat + /showpage {} def + 0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin + 10 setmiterlimit [] 0 setdash newpath + false setstrokeadjust false setoverprint % don't use F +}bd +/cg_EndEPSF{ + countdictstack 3 sub { end } repeat + cg_dict_array 3 1 index length 3 sub getinterval + {begin}forall + count userdict/cg_op_count get sub{pop}repeat + userdict/cg_b4_Inc_state get restore + F setpacking +}bd + +/cg_biproc{currentfile/RunLengthDecode filter}bd +/cg_aiproc{currentfile/ASCII85Decode filter/RunLengthDecode filter}bd +/ImageDataSource 0 def +L3?{ + /cg_mibiproc{pop pop/ImageDataSource{cg_biproc}def}bd + /cg_miaiproc{pop pop/ImageDataSource{cg_aiproc}def}bd +}{ + /ImageBandMask 0 def + /ImageBandData 0 def + /cg_mibiproc{ + string/ImageBandMask xs + string/ImageBandData xs + /ImageDataSource{[currentfile/RunLengthDecode filter dup ImageBandMask/readstring cvx + /pop cvx dup ImageBandData/readstring cvx/pop cvx]cvx bind}bd + }bd + /cg_miaiproc{ + string/ImageBandMask xs + string/ImageBandData xs + /ImageDataSource{[currentfile/ASCII85Decode filter/RunLengthDecode filter + dup ImageBandMask/readstring cvx + /pop cvx dup ImageBandData/readstring cvx/pop cvx]cvx bind}bd + }bd +}ifelse +/imsave 0 def +/BI{save/imsave xd mark}bd +/EI{imsave restore}bd +/ID{ +counttomark 2 idiv +dup 2 add % leave room for imagetype and imagematrix +dict begin +{def} repeat +pop % remove mark +/ImageType 1 def +/ImageMatrix[Width 0 0 Height neg 0 Height]def +currentdict dup/ImageMask known{ImageMask}{F}ifelse exch +% currentdict on stack +L3?{ + dup/MaskedImage known + { + pop + << + /ImageType 3 + /InterleaveType 2 + /DataDict currentdict + /MaskDict + << /ImageType 1 + /Width Width + /Height Height + /ImageMatrix ImageMatrix + /BitsPerComponent 1 + /Decode [0 1] + currentdict/Interpolate known + {/Interpolate Interpolate}if + >> + >> + }if +}if +exch +{imagemask}{image}ifelse +end % pop imagedict from dict stack +}bd + +/cguidfix{statusdict begin mark version end +{cvr}stopped{cleartomark 0}{exch pop}ifelse +2012 lt{dup findfont dup length dict begin +{1 index/FID ne 2 index/UniqueID ne and +{def} {pop pop} ifelse}forall +currentdict end definefont pop +}{pop}ifelse +}bd +/t_array 0 def +/t_i 0 def +/t_c 1 string def +/x_proc{ % x y + exch t_array t_i get add exch moveto + /t_i t_i 1 add store +}bd +/y_proc{ % x y + t_array t_i get add moveto + /t_i t_i 1 add store +}bd +/xy_proc{ + % x y + t_array t_i 2 copy 1 add get 3 1 roll get + 4 -1 roll add 3 1 roll add moveto + /t_i t_i 2 add store +}bd +/sop 0 def % don't bind sop +/cp_proc/x_proc ld % default moveto proc is for xwidths only +/base_charpath % string array +{ + /t_array xs + /t_i 0 def + { % char + t_c 0 3 -1 roll put + currentpoint + t_c cply sop + cp_proc + }forall + /t_array 0 def +}bd +/sop/stroke ld % default sop is stroke. Done here so we don't bind in /base_charpath + +% default sop is stroke +/nop{}def +/xsp/base_charpath ld +/ysp{/cp_proc/y_proc ld base_charpath/cp_proc/x_proc ld}bd +/xysp{/cp_proc/xy_proc ld base_charpath/cp_proc/x_proc ld}bd +/xmp{/sop/nop ld /cp_proc/x_proc ld base_charpath/sop/stroke ld}bd +/ymp{/sop/nop ld /cp_proc/y_proc ld base_charpath/sop/stroke ld}bd +/xymp{/sop/nop ld /cp_proc/xy_proc ld base_charpath/sop/stroke ld}bd +/refnt{ % newname encoding fontname +findfont dup length dict copy dup +/Encoding 4 -1 roll put +definefont pop +}bd +/renmfont{ % newname fontname +findfont dup length dict copy definefont pop +}bd + +L3? dup dup{save exch}if + +% languagelevel2 ONLY code goes here + +/Range 0 def +/DataSource 0 def +/val 0 def +/nRange 0 def +/mulRange 0 def +/d0 0 def +/r0 0 def +/di 0 def +/ri 0 def +/a0 0 def +/a1 0 def +/r1 0 def +/r2 0 def +/dx 0 def +/Nsteps 0 def +/sh3tp 0 def +/ymax 0 def +/ymin 0 def +/xmax 0 def +/xmin 0 def + +/setupFunEval % funDict -- % this calculates and sets up a function dict for evaulation. +{ + begin + /nRange Range length 2 idiv store + /mulRange % precompute the range data needed to map a sample value from the table to a range value + % this data looks like [ range0mul range0min range1mul range1min ... rangeN-1mul rangeN-1min ] + [ + 0 1 nRange 1 sub + { % index + 2 mul/nDim2 xd % 2*dimension# we are dealing with + Range nDim2 get % ymin + Range nDim2 1 add get % ymin ymax + 1 index sub % ymin (ymax-ymin) + % xmin = 0, xmax = 255 (2^bitspersample - 1) + 255 div % ymin (ymax-ymin)/(xmax - xmin) + exch % (ymax-ymin)/(xmax - xmin) ymin + }for + ]store + end +}bd + +/FunEval % val1 fundict -> comp1 comp2 ... compN +{ + begin + % the value passed in is the base index into the table + nRange mul /val xd % compute the actual index to the table + % since there are nRange entries per base index + 0 1 nRange 1 sub + { + dup 2 mul/nDim2 xd % dim + val % base value to use to do our lookup + add DataSource exch get % lookedupval + mulRange nDim2 get mul % lookedupval*(ymax-ymin)/(xmax-xmin) + mulRange nDim2 1 add get % lookedupval*(ymax-ymin)/(xmax-xmin) ymin + add % interpolated result + }for % comp1 comp2 ... compN + end +}bd + +/max % a b -> max(a, b) +{ + 2 copy lt + {exch pop}{pop}ifelse +}bd + +/sh2 +{ % emulation of shading type 2. Assumes shading dictionary is top dictionary on the dict stack + /Coords load aload pop % x0 y0 x1 y1 + 3 index 3 index translate % origin is now at beginning point of shading + % x0 y0 x1 y1 + 3 -1 roll sub % x0 x1 y1-y0 + 3 1 roll exch % y1-y0 x1 x0 + sub % y1-y0 x1-x0 + 2 copy + dup mul exch dup mul add sqrt % length of segment between two points + dup + scale + atan % atan (dy/dx) + %dup (rotation angle = )print == + rotate % now line between 0,0 and 1,0 is the line perpendicular to which the axial lines are drawn + + /Function load setupFunEval % may need to setup function dictionary by calling setupFunEval + + % this is now specific to axial shadings. Compute the maximum bounds to fill + clippath {pathbbox}stopped {0 0 0 0}if newpath % x0 y0 x1 y1 + /ymax xs + /xmax xs + /ymin xs + /xmin xs + currentdict/Extend known + { + /Extend load 0 get + { + 0/Function load FunEval sc % evaluate the function to get a color and set it + xmin ymin xmin abs ymax ymin sub rectfill + }if + }if + % paint the rects. The sampling frequency is that of our table + /Nsteps/Function load/Size get 0 get 1 sub store + /dx 1 Nsteps div store + gsave + /di ymax ymin sub store + /Function load + % loop Nsteps + 1 times, incrementing the index by 1 each time + 0 1 Nsteps + { + 1 index FunEval sc + 0 ymin dx di rectfill + dx 0 translate + }for + pop % pop our function + grestore % origin is back to start point + currentdict/Extend known + { + /Extend load 1 get + { + Nsteps/Function load FunEval sc % last element + 1 ymin xmax 1 sub abs ymax ymin sub rectfill + }if + }if +}bd + +/shp % this paints our shape for shading type 3 +{ % x1 r1 x0 r0 - + 4 copy + + % fill interior arc + dup 0 gt{ + 0 exch a1 a0 arc + }{ + pop 0 moveto + }ifelse + + dup 0 gt{ + 0 exch a0 a1 arcn + }{ + pop 0 lineto + }ifelse + + fill + + % fill exterior arc + dup 0 gt{ + 0 exch a0 a1 arc + }{ + pop 0 moveto + }ifelse + + dup 0 gt{ + 0 exch a1 a0 arcn + }{ + pop 0 lineto + }ifelse + + fill +}bd + +/calcmaxs +{ % calculate maximum distance vector from origin to corner points + % of bbox + xmin dup mul ymin dup mul add sqrt % (xmin2 + ymin2) + xmax dup mul ymin dup mul add sqrt % (xmax2 + ymin2) + xmin dup mul ymax dup mul add sqrt % (xmin2 + ymax2) + xmax dup mul ymax dup mul add sqrt % (xmax2 + ymax2) + max max max % maximum value +}bd + +/sh3 +{ % emulation of shading type 3. Assumes shading dictionary is top dictionary on the dict stack + /Coords load aload pop % x0 y0 r1 x1 y1 r2 + 5 index 5 index translate % origin is now at first circle origin + 3 -1 roll 6 -1 roll sub % y0 r1 y1 r2 dx + 3 -1 roll 5 -1 roll sub % r1 r2 dx dy + 2 copy dup mul exch dup mul add sqrt + /dx xs % r1 r2 dx dy + 2 copy 0 ne exch 0 ne or + { + % r1 r2 dx dy + exch atan rotate % we are now rotated so dy is zero and positive values of dx move us as expected + }{ + pop pop + }ifelse + % r1 r2 + /r2 xs + /r1 xs + /Function load + dup/Size get 0 get 1 sub % this is the size of our table minus 1 + /Nsteps xs % at some point we should optimize this better so NSteps is based on needed steps for the device + setupFunEval % may need to setup function dictionary by calling setupFunEval + % determine the case: + % case 0: circle1 inside circle2 + % case 1: circle 2 inside circle 1 + % case 2: r1 = r2 + % case 3: r1 != r2 + dx r2 add r1 lt{ + % circle 2 inside of circle 1 + 0 + }{ + dx r1 add r2 le + { % circle 1 inside of circle 2 + 1 + }{ % circles don't contain each other + r1 r2 eq + { % equal + 2 + }{ % r1 != r2 + 3 + }ifelse + }ifelse + }ifelse + /sh3tp xs % sh3tp has the number of our different cases + clippath {pathbbox}stopped {0 0 0 0}if + newpath % x0 y0 x1 y1 + /ymax xs + /xmax xs + /ymin xs + /xmin xs + + % Arc angle atan( sqrt((dx*dx + dy*dy) - dr*dr), dr) + dx dup mul r2 r1 sub dup mul sub dup 0 gt + { + sqrt r2 r1 sub atan + /a0 exch 180 exch sub store + /a1 a0 neg store + }{ + pop + /a0 0 store + /a1 360 store + }ifelse + + currentdict/Extend known + { + /Extend load 0 get r1 0 gt and % no need to extend if the radius of the first end is 0 + { + 0/Function load FunEval sc % evaluate the function to get a color and set it + % case 0: circle1 inside circle2 + % case 1: circle 2 inside circle 1 + % case 2: circles don't contain each other and r1 == r2 + % case 3: circles don't contain each other and r1 != r2 + { + { % case 0 + dx 0 r1 360 0 arcn + xmin ymin moveto + xmax ymin lineto + xmax ymax lineto + xmin ymax lineto + xmin ymin lineto + eofill % for the bigger radius we fill everything except our circle + } + { % case 1 + r1 0 gt{0 0 r1 0 360 arc fill}if + } + { % case 2 + % r1 == r2, extend 0 + % r3 = r, x3 = -(abs(minx) + r), x1 = 0 + + % x(i+1) r(i+1) x(i) r(i) shp + 0 r1 xmin abs r1 add neg r1 shp + } + { % case 3 + % no containment, r1 != r2 + + r2 r1 gt{ % the endpoint we are drawing is that with a circle of zero radius + % x(i+1) r(i+1) x(i) r(i) shp + 0 r1 + r1 neg r2 r1 sub div dx mul % this is point of beginning circle + 0 % point of ending circle + shp % takes x(i+1) r(i+1) x(i) r(i) + }{ % the first circle is the bigger of the two + % we find a circle on our line which is outside the bbox in the + % negative direction + % x(i+1) r(i+1) x(i) r(i) shp + 0 r1 calcmaxs % 0 r1 maxs + dup + % calculating xs: (-(maxs+r2)*x2)/(x2-(r1-r2)) + r2 add dx mul dx r1 r2 sub sub div + neg % maxs xs' + exch 1 index % xs' maxs xs' + abs exch sub + shp + }ifelse + } + }sh3tp get exec % execute the extend at beginning proc for our shading type + }if + }if + + % now do the shading + /d0 0 store + /r0 r1 store + /di dx Nsteps div store + /ri r2 r1 sub Nsteps div store + /Function load + 0 1 Nsteps + { % function t(i) + 1 index FunEval sc + d0 di add r0 ri add d0 r0 shp + { + % fill interior arc + d0 0 r0 a1 a0 arc + d0 di add 0 r0 ri add a0 a1 arcn + fill + + % fill exterior arc + d0 0 r0 a0 a1 arc + d0 di add 0 r0 ri add a1 a0 arcn + fill + }pop + + % advance to next + /d0 d0 di add store + /r0 r0 ri add store + }for + pop % pop our function dict + + % handle Extend + currentdict/Extend known + { + /Extend load 1 get r2 0 gt and % no need to extend if the radius of the last end is 0 + { + Nsteps/Function load FunEval sc % last element + % case 0: circle1 inside circle2 + % case 1: circle 2 inside circle 1 + % case 2: circles don't contain each other and r1 == r2 + % case 3: circles don't contain each other and r1 != r2 + { + { + dx 0 r2 0 360 arc fill + } + { + dx 0 r2 360 0 arcn + xmin ymin moveto + xmax ymin lineto + xmax ymax lineto + xmin ymax lineto + xmin ymin lineto + eofill % for the bigger radius we fill everything except our circle + } + { % r1 == r2, extend 1 + % r3 = r, x3 = (abs(xmax) + r), x1 = dx + % x(i+1) r(i+1) x(i) r(i) shp + xmax abs r1 add r1 dx r1 shp + } + { % no containment, r1 != r2 + + r2 r1 gt{ + % we find a circle on our line which is outside the bbox in the + % positive direction + % x(i+1) r(i+1) x(i) r(i) shp + calcmaxs dup % maxs maxs + % calculating xs: ((maxs+r1)*x2)/(x2-(r2-r1)) + r1 add dx mul dx r2 r1 sub sub div % maxs xs + exch 1 index % xs maxs xs + exch sub + dx r2 + shp + }{ % the endpoint we are drawing is that with a circle of zero radius + % x(i+1) r(i+1) x(i) r(i) shp + r1 neg r2 r1 sub div dx mul % this is point of ending circle + 0 % radius of ending circle + dx % point of starting circle + r2 % radius of starting circle + shp + }ifelse + } + } + sh3tp get exec % execute the extend at end proc for our shading type + }if + }if +}bd +/sh % emulation of shfill operator for type 2 and type 3 shadings based on type 0 functions +{ % shadingDict -- + begin + /ShadingType load dup dup 2 eq exch 3 eq or + { % shadingtype + gsave + newpath + /ColorSpace load scs + currentdict/BBox known + { + /BBox load aload pop % llx lly urx ury + 2 index sub % llx lly urx ury-lly + 3 index % llx lly urx ury-lly llx + 3 -1 roll exch sub + exch rectclip + }if + 2 eq + {sh2}{sh3}ifelse + grestore + }{ + % shadingtype + pop + (DEBUG: shading type unimplemented\n)print flush + }ifelse + end +}bd + +% end of language level 2 ONLY code + +{restore}if not dup{save exch}if +% languagelevel3 ONLY code goes here + L3?{ % we do these loads conditionally or else they will fail on a level 2 printer + /sh/shfill ld + /csq/clipsave ld + /csQ/cliprestore ld + }if +{restore}if + +%currentdict dup maxlength exch length sub (number of extra slots in md = )print == flush % *** how many entries are free +end +setpacking +% count 0 ne { pstack(***extras on stack during prolog execution***\n)print flush}if % *** BARK if anything is left on stack +%%EndFile +%%EndProlog +%%BeginSetup +%%EndSetup +%%Page: 1 1 +%%PageBoundingBox: 0 0 39 38 +%%BeginPageSetup +cg_md begin +bp +sdmtx +[ /CIEBasedABC 4 dict dup begin +/WhitePoint [ 0.9505 1.0000 1.0891 ] def +/DecodeABC [ +{ 1.0 0.0 3 -1 roll 1 index 1 index le { exch pop} { pop } ifelse + 1 index 1 index ge { exch pop } { pop } ifelse < +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000001010101010101010101010101 +0101010101010101010101010101010101010101010101020202020202020202 +0202020202020202020202020202020202030303030303030303030303030303 +0303030303030304040404040404040404040404040404040404050505050505 +0505050505050505050506060606060606060606060606060607070707070707 +0707070707070708080808080808080808080808090909090909090909090909 +0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c +0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f10101010 +1010101010111111111111111112121212121212121313131313131313141414 +1414141414151515151515151616161616161616171717171717171818181818 +18181919191919191a1a1a1a1a1a1a1b1b1b1b1b1b1c1c1c1c1c1c1c1d1d1d1d +1d1d1e1e1e1e1e1e1f1f1f1f1f1f202020202020212121212121222222222223 +2323232323242424242425252525252526262626262727272727282828282829 +292929292a2a2a2a2a2b2b2b2b2b2c2c2c2c2c2d2d2d2d2d2e2e2e2e2e2f2f2f +2f2f303030303131313131323232323333333333343434343535353535363636 +36373737373838383839393939393a3a3a3a3b3b3b3b3c3c3c3c3d3d3d3d3e3e +3e3e3f3f3f3f4040404041414141424242424343434444444445454545464646 +4647474748484848494949494a4a4a4b4b4b4b4c4c4c4d4d4d4d4e4e4e4f4f4f +4f50505051515151525252535353535454545555555656565657575758585859 +59595a5a5a5a5b5b5b5c5c5c5d5d5d5e5e5e5f5f5f6060606061616162626263 +63636464646565656666666767676868686969696a6a6a6b6b6b6c6c6d6d6d6e +6e6e6f6f6f707070717171727273737374747475757576767677777878787979 +797a7a7b7b7b7c7c7c7d7d7e7e7e7f7f7f808081818182828283838484848585 +86868687878888888989898a8a8b8b8b8c8c8d8d8d8e8e8f8f90909091919292 +9293939494949595969697979798989999999a9a9b9b9c9c9c9d9d9e9e9f9f9f +a0a0a1a1a2a2a3a3a3a4a4a5a5a6a6a6a7a7a8a8a9a9aaaaabababacacadadae +aeafafb0b0b0b1b1b2b2b3b3b4b4b5b5b6b6b6b7b7b8b8b9b9bababbbbbcbcbd +bdbebebebfbfc0c0c1c1c2c2c3c3c4c4c5c5c6c6c7c7c8c8c9c9cacacbcbcccc +cdcdcececfcfd0d0d1d1d2d2d3d3d4d4d5d5d6d6d7d7d8d8d9d9dadadbdcdcdd +dddededfdfe0e0e1e1e2e2e3e3e4e4e5e6e6e7e7e8e8e9e9eaeaebebecededee +eeefeff0f0f1f1f2f3f3f4f4f5f5f6f6f7f8f8f9f9fafafbfcfcfdfdfefeffff +> dup length 1 sub 3 -1 roll mul dup dup floor cvi exch ceiling + cvi 3 index exch get 4 -1 roll 3 -1 roll get + dup 3 1 roll sub 3 -1 roll dup floor cvi sub mul add 255 div } bind + +{ 1.0 0.0 3 -1 roll 1 index 1 index le { exch pop} { pop } ifelse + 1 index 1 index ge { exch pop } { pop } ifelse < +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000001010101010101010101010101 +0101010101010101010101010101010101010101010101020202020202020202 +0202020202020202020202020202020202030303030303030303030303030303 +0303030303030304040404040404040404040404040404040404050505050505 +0505050505050505050506060606060606060606060606060607070707070707 +0707070707070708080808080808080808080808090909090909090909090909 +0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c +0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f10101010 +1010101010111111111111111112121212121212121313131313131313141414 +1414141414151515151515151616161616161616171717171717171818181818 +18181919191919191a1a1a1a1a1a1a1b1b1b1b1b1b1c1c1c1c1c1c1c1d1d1d1d +1d1d1e1e1e1e1e1e1f1f1f1f1f1f202020202020212121212121222222222223 +2323232323242424242425252525252526262626262727272727282828282829 +292929292a2a2a2a2a2b2b2b2b2b2c2c2c2c2c2d2d2d2d2d2e2e2e2e2e2f2f2f +2f2f303030303131313131323232323333333333343434343535353535363636 +36373737373838383839393939393a3a3a3a3b3b3b3b3c3c3c3c3d3d3d3d3e3e +3e3e3f3f3f3f4040404041414141424242424343434444444445454545464646 +4647474748484848494949494a4a4a4b4b4b4b4c4c4c4d4d4d4d4e4e4e4f4f4f +4f50505051515151525252535353535454545555555656565657575758585859 +59595a5a5a5a5b5b5b5c5c5c5d5d5d5e5e5e5f5f5f6060606061616162626263 +63636464646565656666666767676868686969696a6a6a6b6b6b6c6c6d6d6d6e +6e6e6f6f6f707070717171727273737374747475757576767677777878787979 +797a7a7b7b7b7c7c7c7d7d7e7e7e7f7f7f808081818182828283838484848585 +86868687878888888989898a8a8b8b8b8c8c8d8d8d8e8e8f8f90909091919292 +9293939494949595969697979798989999999a9a9b9b9c9c9c9d9d9e9e9f9f9f +a0a0a1a1a2a2a3a3a3a4a4a5a5a6a6a6a7a7a8a8a9a9aaaaabababacacadadae +aeafafb0b0b0b1b1b2b2b3b3b4b4b5b5b6b6b6b7b7b8b8b9b9bababbbbbcbcbd +bdbebebebfbfc0c0c1c1c2c2c3c3c4c4c5c5c6c6c7c7c8c8c9c9cacacbcbcccc +cdcdcececfcfd0d0d1d1d2d2d3d3d4d4d5d5d6d6d7d7d8d8d9d9dadadbdcdcdd +dddededfdfe0e0e1e1e2e2e3e3e4e4e5e6e6e7e7e8e8e9e9eaeaebebecededee +eeefeff0f0f1f1f2f3f3f4f4f5f5f6f6f7f8f8f9f9fafafbfcfcfdfdfefeffff +> dup length 1 sub 3 -1 roll mul dup dup floor cvi exch ceiling + cvi 3 index exch get 4 -1 roll 3 -1 roll get + dup 3 1 roll sub 3 -1 roll dup floor cvi sub mul add 255 div } bind + +{ 1.0 0.0 3 -1 roll 1 index 1 index le { exch pop} { pop } ifelse + 1 index 1 index ge { exch pop } { pop } ifelse < +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000001010101010101010101010101 +0101010101010101010101010101010101010101010101020202020202020202 +0202020202020202020202020202020202030303030303030303030303030303 +0303030303030304040404040404040404040404040404040404050505050505 +0505050505050505050506060606060606060606060606060607070707070707 +0707070707070708080808080808080808080808090909090909090909090909 +0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c +0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f10101010 +1010101010111111111111111112121212121212121313131313131313141414 +1414141414151515151515151616161616161616171717171717171818181818 +18181919191919191a1a1a1a1a1a1a1b1b1b1b1b1b1c1c1c1c1c1c1c1d1d1d1d +1d1d1e1e1e1e1e1e1f1f1f1f1f1f202020202020212121212121222222222223 +2323232323242424242425252525252526262626262727272727282828282829 +292929292a2a2a2a2a2b2b2b2b2b2c2c2c2c2c2d2d2d2d2d2e2e2e2e2e2f2f2f +2f2f303030303131313131323232323333333333343434343535353535363636 +36373737373838383839393939393a3a3a3a3b3b3b3b3c3c3c3c3d3d3d3d3e3e +3e3e3f3f3f3f4040404041414141424242424343434444444445454545464646 +4647474748484848494949494a4a4a4b4b4b4b4c4c4c4d4d4d4d4e4e4e4f4f4f +4f50505051515151525252535353535454545555555656565657575758585859 +59595a5a5a5a5b5b5b5c5c5c5d5d5d5e5e5e5f5f5f6060606061616162626263 +63636464646565656666666767676868686969696a6a6a6b6b6b6c6c6d6d6d6e +6e6e6f6f6f707070717171727273737374747475757576767677777878787979 +797a7a7b7b7b7c7c7c7d7d7e7e7e7f7f7f808081818182828283838484848585 +86868687878888888989898a8a8b8b8b8c8c8d8d8d8e8e8f8f90909091919292 +9293939494949595969697979798989999999a9a9b9b9c9c9c9d9d9e9e9f9f9f +a0a0a1a1a2a2a3a3a3a4a4a5a5a6a6a6a7a7a8a8a9a9aaaaabababacacadadae +aeafafb0b0b0b1b1b2b2b3b3b4b4b5b5b6b6b6b7b7b8b8b9b9bababbbbbcbcbd +bdbebebebfbfc0c0c1c1c2c2c3c3c4c4c5c5c6c6c7c7c8c8c9c9cacacbcbcccc +cdcdcececfcfd0d0d1d1d2d2d3d3d4d4d5d5d6d6d7d7d8d8d9d9dadadbdcdcdd +dddededfdfe0e0e1e1e2e2e3e3e4e4e5e6e6e7e7e8e8e9e9eaeaebebecededee +eeefeff0f0f1f1f2f3f3f4f4f5f5f6f6f7f8f8f9f9fafafbfcfcfdfdfefeffff +> dup length 1 sub 3 -1 roll mul dup dup floor cvi exch ceiling + cvi 3 index exch get 4 -1 roll 3 -1 roll get + dup 3 1 roll sub 3 -1 roll dup floor cvi sub mul add 255 div } bind +] def +/MatrixABC [ 0.4124 0.2126 0.0193 0.3576 0.7151 0.1192 0.1805 0.0722 0.9508 ] def +/RangeLMN [ 0.0 0.9505 0.0 1.0000 0.0 1.0891 ] def +end ] /Cs1 exch/ColorSpace dr pop +%%EndPageSetup +0.60000002 i +/Cs1 SC +1 1 1 sc +q +0 25.643332 m +25.422678 25.643332 l +25.422678 0.22065477 l +0 0.22065477 l +0 25.643332 l +h +W* +0 0 39 38 rc +0 25.643332 m +25.422678 25.643332 l +25.422678 0.22065477 l +0 0.22065477 l +0 25.643332 l +h +f +Q +2.0678732 w +0.40000001 0.40000001 0.40000001 sc +q +0 25.643332 m +25.422678 25.643332 l +25.422678 0.22065477 l +0 0.22065477 l +0 25.643332 l +h +W* +0 0 39 38 rc +1 0 0 -1 0 25.643332 cm +0 0 m +25.422678 0 l +25.422678 25.422678 l +0 25.422678 l +0 0 l +h +S +Q +q +0 0 39 38 rc +40 0 0 13 -1 25 cm +save +360 15 cg_miaiproc +0 -39 -39{ +gsave 1 120 div 1 39 div scale 0 exch translate +currentfile 0 (EOD +)/SubFileDecode filter +L3?{flushfile}{cvx exec}ifelse +120 40 scale +BI +/Width 120 +/Height 40 +/BitsPerComponent 8 +/Decode[ +0 1 +0 1 +0 1 +] +/DataSource ImageDataSource +/MaskedImage true +ID +EI +grestore} bind for +0 39 m 0 0 l 120 0 l 120 39 l h W n EOD +JcC<$MZ<5IL];r*PQ11Rrr7QLJcD8?nc4OHrpB]]o;$r5Z)%B%rqlTmnc8%VU&Y,QrcWj)k@VD>rdXoe +rqQBjnc4aNrnIEkgLc"Ka_(O+rb_XHrqQBjnc7DD\c;ZVrbMCCrb;A3J[*t7jK\]Zok+2[rb21@rqQBj +nc4sTrl+kMqe#hDrmT3nJcG6>rp'K/ph'Marb2(=rqQBjnc6c2dJs3Tph'MFrn`5+_uKZ7ro3p!ph'Ma +nn.mrqu?3eS,`Jeph'MMro^cjM#[J-rbq[Grb)4gmq2Roqu?3e[f>^orqubcph'MTrpG@;^An2ZrbD=B +rb;@g!+u%=rdOWSrqQBjnc5KcrqQJSph'M]rq)i_T`>#1rb)+?rbVRfph'M`rpKPnrqQBjnc5Tfrq$,D +ph'MhrqV-F^An2Cph'MFrdacUrfmEYrqH8$!G5sCq"t*^!36(umJ_P/B)\G%r.k<^s8K+pB)ZuQHh_4P +T`4ohs8McfB)_T&s7-/ls8M*YG5,\KXSDgHs2Y0=rViJbB)[,UG5,\KXSDhpp\8A"q"t*f!;QW!s8LdP +E;4&E]7L"Ks3q#IqYlcTB)[;ZEVO/F\Fon$p\8A"q"t*^!42_)dJdqYB)ZNDaPd)Ls53kUpAU!FB)[J_ +D>RrEBE#j?s8McfB)_T&s7-0as1n[6`;XHIB)ZWGdt.PKs6K^anc".8B)[VcCAVWBCAuQJs8McfB)_T& +s7-0#s8KM&B)ZfLhT5_Js7cQmli)8+B)[_fB_uE@DuSGVs8McfB)_T&s7-0Os4IANWVC*)GlHlWs1\L6 +jQ$=%rcS!Jrf$VarcA(ul2UbWph'O#qu?3e_Z0W5rg`aqrdXq8YlBdarnIEjqe#h?rf$Vard+S/k5YGT +ph'O#qu?3ee,T%>rqQJSph'M]rq(dA^An2[rbMCCrb2:fq.9V=rdk(r#rqq?I^An2Dph'MErdjiV +rfd?WnGhqVrqH2"rqQBjnc6u8roF'%ph'N,JcG]K^]4;9ph'MJrd4EPrgs,egAh0Hph'O#qu?3edJs4# +rc%XErk%_#JcF$qrr)hjph'MOrcS!Jri5tsf`(sOrqH2"rqQBjnc72>rmC^\qe#hArlBZjjo='7rqcV[ +ph'MTrc7dGrjU;TrqH2"rqQBjnc7;Arl"eLqe#hDrmTR#JcFm4rqHDOph'MYrbhUFrb)5JcN!n1]^JH##Ps8McfB)_T&s7-0Vs8MEbIJ@FRTDnbNs/uD$aSolMB)ZTF +LA5B[M#R%Zs8McfB)_T&s7-0Ys8M*YG5,YMW2K]prqV-A^A@iAph'MErdjiVrf[9Vl2T02rqH2"rqQBj +nc87\rnIEkJS+1Z\n:q`rd=KQrgj&d[f?@$ph'O#qu?3ep&G$=rbLA&JS)o6rd"Keph'N)rr1=Fj8],Q +ph'O#qu?3eq#C?3rb-jpdUpp>rdOieph'N5XoJCpph'O#qu?3eq#A6MJT':]re1/\rb)5H[f?%#rqH2" +rqQBjnc8IbJS)K*jC\CEqe#i:VuQbjph'O#qu;0 +~> 0 40 m 0 39 l 120 39 l 120 40 l h W n EOD +nc8IbJS(Hbre(8`r+>r;VuQbjph'O#JcG<@JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$ +JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$ +JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$ +JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcG!7 +J, +~> restore +14 0 0 25 25 0 cm +save +126 6 cg_miaiproc +38 -37 -36{ +gsave 1 42 div 1 75 div scale 0 exch translate +currentfile 0 (EOD +)/SubFileDecode filter +L3?{flushfile}{cvx exec}ifelse +42 38 scale +BI +/Width 42 +/Height 38 +/BitsPerComponent 8 +/Decode[ +0 1 +0 1 +0 1 +] +/DataSource ImageDataSource +/MaskedImage true +ID +EI +grestore} bind for +0 37 m 0 0 l 42 0 l 42 37 l h W n EOD +JcG]KqZ-V-re1/\rl1l9rqH2"!;HTiq"t*g!<-U0K_oB\`i&k9p\8A"q"t*g!<-U0K_oB\`i&k9pAnl< +qI]a%qu?Nnrau._qe#iIVuQbjph'O#qu?Nnrau._qe#iIWrN(urqH2"rqQBjqZ-V-re1/\rl1l9rqH2" +rqQBjqZ-V-re1/\rl28DpAb-dph'O#qu?Nnrau._qe#iIVuQbjph'O#qu?Nnrau._qe#iI])V3urqH2" +rqQBjqZ-V-re1/\rl1l9rqH2"rqQBjqZ-V-re1/\rl2hTk5YGTph'O#qu?Nnrau._qe#iIVuQbjph'O# +qu?Nnrau._qe#iIb5^>urqH2"rqQBjqZ-V-re1/\rl1l9rqH2"rqQBjqZ-V-re1/\rl3Cdf)PaDph'O# +qu?Nnrau._qe#iIVuQbjph'O#qu?Nnrau._qe#iIgAfIurqH2"rqQBjqZ-V-re1/\rl1l9rqH2"rqQBj +qZ-V-re1/\rl3st`rH&4ph'O#qu?Nnrau._qe#iIVuQbjph'O#qu?Nnrau._qe#iIlMnTurqH2"rqQBj +qZ-V-re1/\rl1l9rqH2"rqQBjqZ-V-re1/\rl4O/[f?@$ph'O#qu?Nnrau._qe#iIVuQbjph'O#qu?Nn +rau._qe#iIqZ!_urqH2"rqQBjqZ-V-re1/\rl1l9rqH2"rqQBjqZ-V-re1/\!QN+Z`i&k9p\8A"q"t*g +!<-U0K_oB\`i&k9p\8A"q"t*g!<-U0K_oB\`i&k9p\8A"q"t*g!<-U0K_oB\`i&k9p\8A"q"t*i!!*'" +rau._qe#iIVuQbjph'O#qu?Nnrau._qe#iIVuQbjph'O#!WW2us8)fqB)[J\B)]fJs8McfB)_T&s8)fq +B)[J\B)]fJs8MciB)ZEAq"t*g!<-U0K_oB\`i&k9p\8A"q"t*g!<-U0K_oB\`i&h:pAt$_ph'O#qu?Nn +rau._qe#iIVuQbjph'O#qu;0 +~> 0 38 m 0 0 l 42 0 l 42 38 l h W n EOD +qZ-V-re1/\rl1l9rqH2"rqQBjqZ-V-re1/\rl1l9rqH2"!;HTiq"t*g!<-U0K_oB\`i&k9p\8A"q"t*g +!<-U0K_oB\`i&k9o`8Z:qI]a%qu?Nnrau._qe#iIWrN(lrf6bcrqQBjqZ-V-re1/\rl2)?rpKc:ph'Me +rr2fpqZ-V-re1/\rl22Bro=!$ph'N!rr)WlqZ-V-re1/\rl2;E!7_,#ec'I]B)].-s8)fqB)[J\B)]fY +s8Kt9C&;NAC&Z-@s8)fqB)[J\B)]f]rrE)uZhS/3DuSATs8)fqB)[J\B)]fbs8MrqTD3$tGQ-[fs8)fq +B)[J\B)]fes8M`kO8*>dK)Y6$s8)fqB)[J\B)]fhs8MHcJbWjVOT,"7s8)fqB)[J\B)]fmrrN0"roF'% +ph'Murqt^SqZ-V-re1/\rl3.]rmq'dph'N3gAh$Mrau._qe#iIdf9:Grl4qOqe#hArl3RiqZ-V-re1/\ +rl3@crj2B3rbqeeeGoCGrau._qe#iIgAh0Prqubgph'MLroDK,qZ-V-re1/\rl3[lrqHDRph'MWrpS/4 +qZ-V-re1/\rl3str;ZcardsoWrf@'QbQ%G>rau._qe#iIi;`f;rc\'Krh08gaT),;rau._qe#iIlMp_\ +rmq'dph'N2_Z0K5rau._qe#iIk5YG#rb;7Arb;AN^]402rau._qe#iIo)JLbrj;H4rbh_d]`7j/rau._ +qe#iIn,NCbrh0$urceA&\c;O,rau._qe#iIqZ$BkrqHDRph'MVrpR;qqZ-V-re1/\rl4X2rpTi 0 38 m 0 36 l 42 36 l 42 38 l h W n EOD +qZ-V-reg^*N;rbTrlb<)OoL"4JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$ +JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$l2Q8 +~> restore +ep +end +%%Trailer +%%EOF diff --git a/img/yellow.eps b/img/yellow.eps new file mode 100644 index 0000000..38989e0 --- /dev/null +++ b/img/yellow.eps @@ -0,0 +1,1153 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%APL_DSC_Encoding: UTF8 +%%Title: (Unknown) +%%Creator: (Unknown) +%%CreationDate: (Unknown) +%%For: (Unknown) +%%DocumentData: Clean7Bit +%%LanguageLevel: 2 +%%Pages: 1 +%%BoundingBox: 0 0 39 38 +%%EndComments +%%BeginProlog +%%BeginFile: cg-pdf.ps +%%Copyright: Copyright 2000-2004 Apple Computer Incorporated. +%%Copyright: All Rights Reserved. +currentpacking true setpacking +/cg_md 141 dict def +cg_md begin +/L3? languagelevel 3 ge def +/bd{bind def}bind def +/ld{load def}bd +/xs{exch store}bd +/xd{exch def}bd +/cmmtx matrix def +mark +/sc/setcolor +/scs/setcolorspace +/dr/defineresource +/fr/findresource +/T/true +/F/false +/d/setdash +/w/setlinewidth +/J/setlinecap +/j/setlinejoin +/M/setmiterlimit +/i/setflat +/rc/rectclip +/rf/rectfill +/rs/rectstroke +/f/fill +/f*/eofill +/sf/selectfont +/s/show +%/as/ashow +/xS/xshow +/yS/yshow +/xyS/xyshow +/S/stroke +/m/moveto +/l/lineto +/c/curveto +/h/closepath +/n/newpath +/q/gsave +/Q/grestore +counttomark 2 idiv +%dup (number of ld's = )print == flush % *** how many +{ld}repeat pop +/SC{ % CSname + /ColorSpace fr scs +}bd +/sopr /setoverprint where{pop/setoverprint}{/pop}ifelse ld +/soprm /setoverprintmode where{pop/setoverprintmode}{/pop}ifelse ld +/cgmtx matrix def +/sdmtx{cgmtx currentmatrix pop}bd +/CM {cgmtx setmatrix}bd % pop the ctm: our gstate ctm on host is now identity +/cm {cmmtx astore CM concat}bd % reset the matrix and then concat +/W{clip newpath}bd +/W*{eoclip newpath}bd + +statusdict begin product end dup (HP) anchorsearch{ + pop pop pop % pop off the search results + true +}{ + pop % previous search result + (hp) anchorsearch{ + pop pop true + }{ + pop false + }ifelse +}ifelse + +{ % HP is the product: we use this method of stroking because of a bug in their clone printers with certain T3 fonts + { + { % charCode Wx Wy + pop pop % charCode + (0)dup 0 4 -1 roll put + F charpath + }cshow + } +}{ + {F charpath} +}ifelse +/cply exch bd +/cps {cply stroke}bd +/pgsave 0 def +/bp{/pgsave save store}bd +/ep{pgsave restore showpage}def % dont' bind +/re{4 2 roll m 1 index 0 rlineto 0 exch rlineto neg 0 rlineto h}bd + +/scrdict 10 dict def +/scrmtx matrix def +/patarray 0 def +/createpat{patarray 3 1 roll put}bd +/makepat{ +scrmtx astore pop +gsave +initgraphics +CM +patarray exch get +scrmtx +makepattern +grestore +setpattern +}bd + +/cg_BeginEPSF{ + userdict save/cg_b4_Inc_state exch put + userdict/cg_endepsf/cg_EndEPSF load put + count userdict/cg_op_count 3 -1 roll put + countdictstack dup array dictstack userdict/cg_dict_array 3 -1 roll put + 3 sub{end}repeat + /showpage {} def + 0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin + 10 setmiterlimit [] 0 setdash newpath + false setstrokeadjust false setoverprint % don't use F +}bd +/cg_EndEPSF{ + countdictstack 3 sub { end } repeat + cg_dict_array 3 1 index length 3 sub getinterval + {begin}forall + count userdict/cg_op_count get sub{pop}repeat + userdict/cg_b4_Inc_state get restore + F setpacking +}bd + +/cg_biproc{currentfile/RunLengthDecode filter}bd +/cg_aiproc{currentfile/ASCII85Decode filter/RunLengthDecode filter}bd +/ImageDataSource 0 def +L3?{ + /cg_mibiproc{pop pop/ImageDataSource{cg_biproc}def}bd + /cg_miaiproc{pop pop/ImageDataSource{cg_aiproc}def}bd +}{ + /ImageBandMask 0 def + /ImageBandData 0 def + /cg_mibiproc{ + string/ImageBandMask xs + string/ImageBandData xs + /ImageDataSource{[currentfile/RunLengthDecode filter dup ImageBandMask/readstring cvx + /pop cvx dup ImageBandData/readstring cvx/pop cvx]cvx bind}bd + }bd + /cg_miaiproc{ + string/ImageBandMask xs + string/ImageBandData xs + /ImageDataSource{[currentfile/ASCII85Decode filter/RunLengthDecode filter + dup ImageBandMask/readstring cvx + /pop cvx dup ImageBandData/readstring cvx/pop cvx]cvx bind}bd + }bd +}ifelse +/imsave 0 def +/BI{save/imsave xd mark}bd +/EI{imsave restore}bd +/ID{ +counttomark 2 idiv +dup 2 add % leave room for imagetype and imagematrix +dict begin +{def} repeat +pop % remove mark +/ImageType 1 def +/ImageMatrix[Width 0 0 Height neg 0 Height]def +currentdict dup/ImageMask known{ImageMask}{F}ifelse exch +% currentdict on stack +L3?{ + dup/MaskedImage known + { + pop + << + /ImageType 3 + /InterleaveType 2 + /DataDict currentdict + /MaskDict + << /ImageType 1 + /Width Width + /Height Height + /ImageMatrix ImageMatrix + /BitsPerComponent 1 + /Decode [0 1] + currentdict/Interpolate known + {/Interpolate Interpolate}if + >> + >> + }if +}if +exch +{imagemask}{image}ifelse +end % pop imagedict from dict stack +}bd + +/cguidfix{statusdict begin mark version end +{cvr}stopped{cleartomark 0}{exch pop}ifelse +2012 lt{dup findfont dup length dict begin +{1 index/FID ne 2 index/UniqueID ne and +{def} {pop pop} ifelse}forall +currentdict end definefont pop +}{pop}ifelse +}bd +/t_array 0 def +/t_i 0 def +/t_c 1 string def +/x_proc{ % x y + exch t_array t_i get add exch moveto + /t_i t_i 1 add store +}bd +/y_proc{ % x y + t_array t_i get add moveto + /t_i t_i 1 add store +}bd +/xy_proc{ + % x y + t_array t_i 2 copy 1 add get 3 1 roll get + 4 -1 roll add 3 1 roll add moveto + /t_i t_i 2 add store +}bd +/sop 0 def % don't bind sop +/cp_proc/x_proc ld % default moveto proc is for xwidths only +/base_charpath % string array +{ + /t_array xs + /t_i 0 def + { % char + t_c 0 3 -1 roll put + currentpoint + t_c cply sop + cp_proc + }forall + /t_array 0 def +}bd +/sop/stroke ld % default sop is stroke. Done here so we don't bind in /base_charpath + +% default sop is stroke +/nop{}def +/xsp/base_charpath ld +/ysp{/cp_proc/y_proc ld base_charpath/cp_proc/x_proc ld}bd +/xysp{/cp_proc/xy_proc ld base_charpath/cp_proc/x_proc ld}bd +/xmp{/sop/nop ld /cp_proc/x_proc ld base_charpath/sop/stroke ld}bd +/ymp{/sop/nop ld /cp_proc/y_proc ld base_charpath/sop/stroke ld}bd +/xymp{/sop/nop ld /cp_proc/xy_proc ld base_charpath/sop/stroke ld}bd +/refnt{ % newname encoding fontname +findfont dup length dict copy dup +/Encoding 4 -1 roll put +definefont pop +}bd +/renmfont{ % newname fontname +findfont dup length dict copy definefont pop +}bd + +L3? dup dup{save exch}if + +% languagelevel2 ONLY code goes here + +/Range 0 def +/DataSource 0 def +/val 0 def +/nRange 0 def +/mulRange 0 def +/d0 0 def +/r0 0 def +/di 0 def +/ri 0 def +/a0 0 def +/a1 0 def +/r1 0 def +/r2 0 def +/dx 0 def +/Nsteps 0 def +/sh3tp 0 def +/ymax 0 def +/ymin 0 def +/xmax 0 def +/xmin 0 def + +/setupFunEval % funDict -- % this calculates and sets up a function dict for evaulation. +{ + begin + /nRange Range length 2 idiv store + /mulRange % precompute the range data needed to map a sample value from the table to a range value + % this data looks like [ range0mul range0min range1mul range1min ... rangeN-1mul rangeN-1min ] + [ + 0 1 nRange 1 sub + { % index + 2 mul/nDim2 xd % 2*dimension# we are dealing with + Range nDim2 get % ymin + Range nDim2 1 add get % ymin ymax + 1 index sub % ymin (ymax-ymin) + % xmin = 0, xmax = 255 (2^bitspersample - 1) + 255 div % ymin (ymax-ymin)/(xmax - xmin) + exch % (ymax-ymin)/(xmax - xmin) ymin + }for + ]store + end +}bd + +/FunEval % val1 fundict -> comp1 comp2 ... compN +{ + begin + % the value passed in is the base index into the table + nRange mul /val xd % compute the actual index to the table + % since there are nRange entries per base index + 0 1 nRange 1 sub + { + dup 2 mul/nDim2 xd % dim + val % base value to use to do our lookup + add DataSource exch get % lookedupval + mulRange nDim2 get mul % lookedupval*(ymax-ymin)/(xmax-xmin) + mulRange nDim2 1 add get % lookedupval*(ymax-ymin)/(xmax-xmin) ymin + add % interpolated result + }for % comp1 comp2 ... compN + end +}bd + +/max % a b -> max(a, b) +{ + 2 copy lt + {exch pop}{pop}ifelse +}bd + +/sh2 +{ % emulation of shading type 2. Assumes shading dictionary is top dictionary on the dict stack + /Coords load aload pop % x0 y0 x1 y1 + 3 index 3 index translate % origin is now at beginning point of shading + % x0 y0 x1 y1 + 3 -1 roll sub % x0 x1 y1-y0 + 3 1 roll exch % y1-y0 x1 x0 + sub % y1-y0 x1-x0 + 2 copy + dup mul exch dup mul add sqrt % length of segment between two points + dup + scale + atan % atan (dy/dx) + %dup (rotation angle = )print == + rotate % now line between 0,0 and 1,0 is the line perpendicular to which the axial lines are drawn + + /Function load setupFunEval % may need to setup function dictionary by calling setupFunEval + + % this is now specific to axial shadings. Compute the maximum bounds to fill + clippath {pathbbox}stopped {0 0 0 0}if newpath % x0 y0 x1 y1 + /ymax xs + /xmax xs + /ymin xs + /xmin xs + currentdict/Extend known + { + /Extend load 0 get + { + 0/Function load FunEval sc % evaluate the function to get a color and set it + xmin ymin xmin abs ymax ymin sub rectfill + }if + }if + % paint the rects. The sampling frequency is that of our table + /Nsteps/Function load/Size get 0 get 1 sub store + /dx 1 Nsteps div store + gsave + /di ymax ymin sub store + /Function load + % loop Nsteps + 1 times, incrementing the index by 1 each time + 0 1 Nsteps + { + 1 index FunEval sc + 0 ymin dx di rectfill + dx 0 translate + }for + pop % pop our function + grestore % origin is back to start point + currentdict/Extend known + { + /Extend load 1 get + { + Nsteps/Function load FunEval sc % last element + 1 ymin xmax 1 sub abs ymax ymin sub rectfill + }if + }if +}bd + +/shp % this paints our shape for shading type 3 +{ % x1 r1 x0 r0 - + 4 copy + + % fill interior arc + dup 0 gt{ + 0 exch a1 a0 arc + }{ + pop 0 moveto + }ifelse + + dup 0 gt{ + 0 exch a0 a1 arcn + }{ + pop 0 lineto + }ifelse + + fill + + % fill exterior arc + dup 0 gt{ + 0 exch a0 a1 arc + }{ + pop 0 moveto + }ifelse + + dup 0 gt{ + 0 exch a1 a0 arcn + }{ + pop 0 lineto + }ifelse + + fill +}bd + +/calcmaxs +{ % calculate maximum distance vector from origin to corner points + % of bbox + xmin dup mul ymin dup mul add sqrt % (xmin2 + ymin2) + xmax dup mul ymin dup mul add sqrt % (xmax2 + ymin2) + xmin dup mul ymax dup mul add sqrt % (xmin2 + ymax2) + xmax dup mul ymax dup mul add sqrt % (xmax2 + ymax2) + max max max % maximum value +}bd + +/sh3 +{ % emulation of shading type 3. Assumes shading dictionary is top dictionary on the dict stack + /Coords load aload pop % x0 y0 r1 x1 y1 r2 + 5 index 5 index translate % origin is now at first circle origin + 3 -1 roll 6 -1 roll sub % y0 r1 y1 r2 dx + 3 -1 roll 5 -1 roll sub % r1 r2 dx dy + 2 copy dup mul exch dup mul add sqrt + /dx xs % r1 r2 dx dy + 2 copy 0 ne exch 0 ne or + { + % r1 r2 dx dy + exch atan rotate % we are now rotated so dy is zero and positive values of dx move us as expected + }{ + pop pop + }ifelse + % r1 r2 + /r2 xs + /r1 xs + /Function load + dup/Size get 0 get 1 sub % this is the size of our table minus 1 + /Nsteps xs % at some point we should optimize this better so NSteps is based on needed steps for the device + setupFunEval % may need to setup function dictionary by calling setupFunEval + % determine the case: + % case 0: circle1 inside circle2 + % case 1: circle 2 inside circle 1 + % case 2: r1 = r2 + % case 3: r1 != r2 + dx r2 add r1 lt{ + % circle 2 inside of circle 1 + 0 + }{ + dx r1 add r2 le + { % circle 1 inside of circle 2 + 1 + }{ % circles don't contain each other + r1 r2 eq + { % equal + 2 + }{ % r1 != r2 + 3 + }ifelse + }ifelse + }ifelse + /sh3tp xs % sh3tp has the number of our different cases + clippath {pathbbox}stopped {0 0 0 0}if + newpath % x0 y0 x1 y1 + /ymax xs + /xmax xs + /ymin xs + /xmin xs + + % Arc angle atan( sqrt((dx*dx + dy*dy) - dr*dr), dr) + dx dup mul r2 r1 sub dup mul sub dup 0 gt + { + sqrt r2 r1 sub atan + /a0 exch 180 exch sub store + /a1 a0 neg store + }{ + pop + /a0 0 store + /a1 360 store + }ifelse + + currentdict/Extend known + { + /Extend load 0 get r1 0 gt and % no need to extend if the radius of the first end is 0 + { + 0/Function load FunEval sc % evaluate the function to get a color and set it + % case 0: circle1 inside circle2 + % case 1: circle 2 inside circle 1 + % case 2: circles don't contain each other and r1 == r2 + % case 3: circles don't contain each other and r1 != r2 + { + { % case 0 + dx 0 r1 360 0 arcn + xmin ymin moveto + xmax ymin lineto + xmax ymax lineto + xmin ymax lineto + xmin ymin lineto + eofill % for the bigger radius we fill everything except our circle + } + { % case 1 + r1 0 gt{0 0 r1 0 360 arc fill}if + } + { % case 2 + % r1 == r2, extend 0 + % r3 = r, x3 = -(abs(minx) + r), x1 = 0 + + % x(i+1) r(i+1) x(i) r(i) shp + 0 r1 xmin abs r1 add neg r1 shp + } + { % case 3 + % no containment, r1 != r2 + + r2 r1 gt{ % the endpoint we are drawing is that with a circle of zero radius + % x(i+1) r(i+1) x(i) r(i) shp + 0 r1 + r1 neg r2 r1 sub div dx mul % this is point of beginning circle + 0 % point of ending circle + shp % takes x(i+1) r(i+1) x(i) r(i) + }{ % the first circle is the bigger of the two + % we find a circle on our line which is outside the bbox in the + % negative direction + % x(i+1) r(i+1) x(i) r(i) shp + 0 r1 calcmaxs % 0 r1 maxs + dup + % calculating xs: (-(maxs+r2)*x2)/(x2-(r1-r2)) + r2 add dx mul dx r1 r2 sub sub div + neg % maxs xs' + exch 1 index % xs' maxs xs' + abs exch sub + shp + }ifelse + } + }sh3tp get exec % execute the extend at beginning proc for our shading type + }if + }if + + % now do the shading + /d0 0 store + /r0 r1 store + /di dx Nsteps div store + /ri r2 r1 sub Nsteps div store + /Function load + 0 1 Nsteps + { % function t(i) + 1 index FunEval sc + d0 di add r0 ri add d0 r0 shp + { + % fill interior arc + d0 0 r0 a1 a0 arc + d0 di add 0 r0 ri add a0 a1 arcn + fill + + % fill exterior arc + d0 0 r0 a0 a1 arc + d0 di add 0 r0 ri add a1 a0 arcn + fill + }pop + + % advance to next + /d0 d0 di add store + /r0 r0 ri add store + }for + pop % pop our function dict + + % handle Extend + currentdict/Extend known + { + /Extend load 1 get r2 0 gt and % no need to extend if the radius of the last end is 0 + { + Nsteps/Function load FunEval sc % last element + % case 0: circle1 inside circle2 + % case 1: circle 2 inside circle 1 + % case 2: circles don't contain each other and r1 == r2 + % case 3: circles don't contain each other and r1 != r2 + { + { + dx 0 r2 0 360 arc fill + } + { + dx 0 r2 360 0 arcn + xmin ymin moveto + xmax ymin lineto + xmax ymax lineto + xmin ymax lineto + xmin ymin lineto + eofill % for the bigger radius we fill everything except our circle + } + { % r1 == r2, extend 1 + % r3 = r, x3 = (abs(xmax) + r), x1 = dx + % x(i+1) r(i+1) x(i) r(i) shp + xmax abs r1 add r1 dx r1 shp + } + { % no containment, r1 != r2 + + r2 r1 gt{ + % we find a circle on our line which is outside the bbox in the + % positive direction + % x(i+1) r(i+1) x(i) r(i) shp + calcmaxs dup % maxs maxs + % calculating xs: ((maxs+r1)*x2)/(x2-(r2-r1)) + r1 add dx mul dx r2 r1 sub sub div % maxs xs + exch 1 index % xs maxs xs + exch sub + dx r2 + shp + }{ % the endpoint we are drawing is that with a circle of zero radius + % x(i+1) r(i+1) x(i) r(i) shp + r1 neg r2 r1 sub div dx mul % this is point of ending circle + 0 % radius of ending circle + dx % point of starting circle + r2 % radius of starting circle + shp + }ifelse + } + } + sh3tp get exec % execute the extend at end proc for our shading type + }if + }if +}bd +/sh % emulation of shfill operator for type 2 and type 3 shadings based on type 0 functions +{ % shadingDict -- + begin + /ShadingType load dup dup 2 eq exch 3 eq or + { % shadingtype + gsave + newpath + /ColorSpace load scs + currentdict/BBox known + { + /BBox load aload pop % llx lly urx ury + 2 index sub % llx lly urx ury-lly + 3 index % llx lly urx ury-lly llx + 3 -1 roll exch sub + exch rectclip + }if + 2 eq + {sh2}{sh3}ifelse + grestore + }{ + % shadingtype + pop + (DEBUG: shading type unimplemented\n)print flush + }ifelse + end +}bd + +% end of language level 2 ONLY code + +{restore}if not dup{save exch}if +% languagelevel3 ONLY code goes here + L3?{ % we do these loads conditionally or else they will fail on a level 2 printer + /sh/shfill ld + /csq/clipsave ld + /csQ/cliprestore ld + }if +{restore}if + +%currentdict dup maxlength exch length sub (number of extra slots in md = )print == flush % *** how many entries are free +end +setpacking +% count 0 ne { pstack(***extras on stack during prolog execution***\n)print flush}if % *** BARK if anything is left on stack +%%EndFile +%%EndProlog +%%BeginSetup +%%EndSetup +%%Page: 1 1 +%%PageBoundingBox: 0 0 39 38 +%%BeginPageSetup +cg_md begin +bp +sdmtx +[ /CIEBasedABC 4 dict dup begin +/WhitePoint [ 0.9505 1.0000 1.0891 ] def +/DecodeABC [ +{ 1.0 0.0 3 -1 roll 1 index 1 index le { exch pop} { pop } ifelse + 1 index 1 index ge { exch pop } { pop } ifelse < +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000001010101010101010101010101 +0101010101010101010101010101010101010101010101020202020202020202 +0202020202020202020202020202020202030303030303030303030303030303 +0303030303030304040404040404040404040404040404040404050505050505 +0505050505050505050506060606060606060606060606060607070707070707 +0707070707070708080808080808080808080808090909090909090909090909 +0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c +0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f10101010 +1010101010111111111111111112121212121212121313131313131313141414 +1414141414151515151515151616161616161616171717171717171818181818 +18181919191919191a1a1a1a1a1a1a1b1b1b1b1b1b1c1c1c1c1c1c1c1d1d1d1d +1d1d1e1e1e1e1e1e1f1f1f1f1f1f202020202020212121212121222222222223 +2323232323242424242425252525252526262626262727272727282828282829 +292929292a2a2a2a2a2b2b2b2b2b2c2c2c2c2c2d2d2d2d2d2e2e2e2e2e2f2f2f +2f2f303030303131313131323232323333333333343434343535353535363636 +36373737373838383839393939393a3a3a3a3b3b3b3b3c3c3c3c3d3d3d3d3e3e +3e3e3f3f3f3f4040404041414141424242424343434444444445454545464646 +4647474748484848494949494a4a4a4b4b4b4b4c4c4c4d4d4d4d4e4e4e4f4f4f +4f50505051515151525252535353535454545555555656565657575758585859 +59595a5a5a5a5b5b5b5c5c5c5d5d5d5e5e5e5f5f5f6060606061616162626263 +63636464646565656666666767676868686969696a6a6a6b6b6b6c6c6d6d6d6e +6e6e6f6f6f707070717171727273737374747475757576767677777878787979 +797a7a7b7b7b7c7c7c7d7d7e7e7e7f7f7f808081818182828283838484848585 +86868687878888888989898a8a8b8b8b8c8c8d8d8d8e8e8f8f90909091919292 +9293939494949595969697979798989999999a9a9b9b9c9c9c9d9d9e9e9f9f9f +a0a0a1a1a2a2a3a3a3a4a4a5a5a6a6a6a7a7a8a8a9a9aaaaabababacacadadae +aeafafb0b0b0b1b1b2b2b3b3b4b4b5b5b6b6b6b7b7b8b8b9b9bababbbbbcbcbd +bdbebebebfbfc0c0c1c1c2c2c3c3c4c4c5c5c6c6c7c7c8c8c9c9cacacbcbcccc +cdcdcececfcfd0d0d1d1d2d2d3d3d4d4d5d5d6d6d7d7d8d8d9d9dadadbdcdcdd +dddededfdfe0e0e1e1e2e2e3e3e4e4e5e6e6e7e7e8e8e9e9eaeaebebecededee +eeefeff0f0f1f1f2f3f3f4f4f5f5f6f6f7f8f8f9f9fafafbfcfcfdfdfefeffff +> dup length 1 sub 3 -1 roll mul dup dup floor cvi exch ceiling + cvi 3 index exch get 4 -1 roll 3 -1 roll get + dup 3 1 roll sub 3 -1 roll dup floor cvi sub mul add 255 div } bind + +{ 1.0 0.0 3 -1 roll 1 index 1 index le { exch pop} { pop } ifelse + 1 index 1 index ge { exch pop } { pop } ifelse < +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000001010101010101010101010101 +0101010101010101010101010101010101010101010101020202020202020202 +0202020202020202020202020202020202030303030303030303030303030303 +0303030303030304040404040404040404040404040404040404050505050505 +0505050505050505050506060606060606060606060606060607070707070707 +0707070707070708080808080808080808080808090909090909090909090909 +0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c +0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f10101010 +1010101010111111111111111112121212121212121313131313131313141414 +1414141414151515151515151616161616161616171717171717171818181818 +18181919191919191a1a1a1a1a1a1a1b1b1b1b1b1b1c1c1c1c1c1c1c1d1d1d1d +1d1d1e1e1e1e1e1e1f1f1f1f1f1f202020202020212121212121222222222223 +2323232323242424242425252525252526262626262727272727282828282829 +292929292a2a2a2a2a2b2b2b2b2b2c2c2c2c2c2d2d2d2d2d2e2e2e2e2e2f2f2f +2f2f303030303131313131323232323333333333343434343535353535363636 +36373737373838383839393939393a3a3a3a3b3b3b3b3c3c3c3c3d3d3d3d3e3e +3e3e3f3f3f3f4040404041414141424242424343434444444445454545464646 +4647474748484848494949494a4a4a4b4b4b4b4c4c4c4d4d4d4d4e4e4e4f4f4f +4f50505051515151525252535353535454545555555656565657575758585859 +59595a5a5a5a5b5b5b5c5c5c5d5d5d5e5e5e5f5f5f6060606061616162626263 +63636464646565656666666767676868686969696a6a6a6b6b6b6c6c6d6d6d6e +6e6e6f6f6f707070717171727273737374747475757576767677777878787979 +797a7a7b7b7b7c7c7c7d7d7e7e7e7f7f7f808081818182828283838484848585 +86868687878888888989898a8a8b8b8b8c8c8d8d8d8e8e8f8f90909091919292 +9293939494949595969697979798989999999a9a9b9b9c9c9c9d9d9e9e9f9f9f +a0a0a1a1a2a2a3a3a3a4a4a5a5a6a6a6a7a7a8a8a9a9aaaaabababacacadadae +aeafafb0b0b0b1b1b2b2b3b3b4b4b5b5b6b6b6b7b7b8b8b9b9bababbbbbcbcbd +bdbebebebfbfc0c0c1c1c2c2c3c3c4c4c5c5c6c6c7c7c8c8c9c9cacacbcbcccc +cdcdcececfcfd0d0d1d1d2d2d3d3d4d4d5d5d6d6d7d7d8d8d9d9dadadbdcdcdd +dddededfdfe0e0e1e1e2e2e3e3e4e4e5e6e6e7e7e8e8e9e9eaeaebebecededee +eeefeff0f0f1f1f2f3f3f4f4f5f5f6f6f7f8f8f9f9fafafbfcfcfdfdfefeffff +> dup length 1 sub 3 -1 roll mul dup dup floor cvi exch ceiling + cvi 3 index exch get 4 -1 roll 3 -1 roll get + dup 3 1 roll sub 3 -1 roll dup floor cvi sub mul add 255 div } bind + +{ 1.0 0.0 3 -1 roll 1 index 1 index le { exch pop} { pop } ifelse + 1 index 1 index ge { exch pop } { pop } ifelse < +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000001010101010101010101010101 +0101010101010101010101010101010101010101010101020202020202020202 +0202020202020202020202020202020202030303030303030303030303030303 +0303030303030304040404040404040404040404040404040404050505050505 +0505050505050505050506060606060606060606060606060607070707070707 +0707070707070708080808080808080808080808090909090909090909090909 +0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c +0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f10101010 +1010101010111111111111111112121212121212121313131313131313141414 +1414141414151515151515151616161616161616171717171717171818181818 +18181919191919191a1a1a1a1a1a1a1b1b1b1b1b1b1c1c1c1c1c1c1c1d1d1d1d +1d1d1e1e1e1e1e1e1f1f1f1f1f1f202020202020212121212121222222222223 +2323232323242424242425252525252526262626262727272727282828282829 +292929292a2a2a2a2a2b2b2b2b2b2c2c2c2c2c2d2d2d2d2d2e2e2e2e2e2f2f2f +2f2f303030303131313131323232323333333333343434343535353535363636 +36373737373838383839393939393a3a3a3a3b3b3b3b3c3c3c3c3d3d3d3d3e3e +3e3e3f3f3f3f4040404041414141424242424343434444444445454545464646 +4647474748484848494949494a4a4a4b4b4b4b4c4c4c4d4d4d4d4e4e4e4f4f4f +4f50505051515151525252535353535454545555555656565657575758585859 +59595a5a5a5a5b5b5b5c5c5c5d5d5d5e5e5e5f5f5f6060606061616162626263 +63636464646565656666666767676868686969696a6a6a6b6b6b6c6c6d6d6d6e +6e6e6f6f6f707070717171727273737374747475757576767677777878787979 +797a7a7b7b7b7c7c7c7d7d7e7e7e7f7f7f808081818182828283838484848585 +86868687878888888989898a8a8b8b8b8c8c8d8d8d8e8e8f8f90909091919292 +9293939494949595969697979798989999999a9a9b9b9c9c9c9d9d9e9e9f9f9f +a0a0a1a1a2a2a3a3a3a4a4a5a5a6a6a6a7a7a8a8a9a9aaaaabababacacadadae +aeafafb0b0b0b1b1b2b2b3b3b4b4b5b5b6b6b6b7b7b8b8b9b9bababbbbbcbcbd +bdbebebebfbfc0c0c1c1c2c2c3c3c4c4c5c5c6c6c7c7c8c8c9c9cacacbcbcccc +cdcdcececfcfd0d0d1d1d2d2d3d3d4d4d5d5d6d6d7d7d8d8d9d9dadadbdcdcdd +dddededfdfe0e0e1e1e2e2e3e3e4e4e5e6e6e7e7e8e8e9e9eaeaebebecededee +eeefeff0f0f1f1f2f3f3f4f4f5f5f6f6f7f8f8f9f9fafafbfcfcfdfdfefeffff +> dup length 1 sub 3 -1 roll mul dup dup floor cvi exch ceiling + cvi 3 index exch get 4 -1 roll 3 -1 roll get + dup 3 1 roll sub 3 -1 roll dup floor cvi sub mul add 255 div } bind +] def +/MatrixABC [ 0.4124 0.2126 0.0193 0.3576 0.7151 0.1192 0.1805 0.0722 0.9508 ] def +/RangeLMN [ 0.0 0.9505 0.0 1.0000 0.0 1.0891 ] def +end ] /Cs1 exch/ColorSpace dr pop +%%EndPageSetup +0.60000002 i +/Cs1 SC +0.85784614 0.87028235 0.11358673 sc +q +0 25.643332 m +25.422678 25.643332 l +25.422678 0.22065477 l +0 0.22065477 l +0 25.643332 l +h +W* +0 0 39 38 rc +0 25.643332 m +25.422678 25.643332 l +25.422678 0.22065477 l +0 0.22065477 l +0 25.643332 l +h +f +Q +2.0678732 w +0.40000001 0.40000001 0.40000001 sc +q +0 25.643332 m +25.422678 25.643332 l +25.422678 0.22065477 l +0 0.22065477 l +0 25.643332 l +h +W* +0 0 39 38 rc +1 0 0 -1 0 25.643332 cm +0 0 m +25.422678 0 l +25.422678 25.422678 l +0 25.422678 l +0 0 l +h +S +Q +q +0 0 39 38 rc +40 0 0 13 -1 25 cm +save +360 15 cg_miaiproc +0 -39 -39{ +gsave 1 120 div 1 39 div scale 0 exch translate +currentfile 0 (EOD +)/SubFileDecode filter +L3?{flushfile}{cvx exec}ifelse +120 40 scale +BI +/Width 120 +/Height 40 +/BitsPerComponent 8 +/Decode[ +0 1 +0 1 +0 1 +] +/DataSource ImageDataSource +/MaskedImage true +ID +EI +grestore} bind for +0 39 m 0 0 l 120 0 l 120 39 l h W n EOD +JcC<$MZ<5IL];r*PQ11Rrr7QLJcD8?nc4OHrpB]]o;$r5Z)%B%rqlTmnc8%VU&Y,QrcWj)k@VD>rdXoe +rqQBjnc4aNrnIEkgLc"Ka_(O+rb_XHrqQBjnc7DD\c;ZVrbMCCIqWM+R[ZadhAtA-*S]EkgYNt*hAtA-*QlVSF`q$bB)[bgB_Z3=q"t*^!6G2fs8KM&Aq+]9@)9c4gYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYP:XhAtA- +*Q?&KEH,@\B)[b[B)_T&s7-/Zs8K"mAl!Ji?-(2;gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYRB"gYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Ek +gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Ek^;)@;D.3^orqubc +ph##$H52_/q"t*^!2TYoq#6BMAnQXFAq,Vn:tF;AgYNt*hAtA-*S]EkgYNt*hAtA-*S]Ek +gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYP[GgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkV5HLhAnCjOrc.pfpgsegMGMjX ++4]!dqITb?B)_T&s7-/is8MEbIJ@E(P*8Mkg`G5,*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-9-)dD*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAr,W7/1BnG5cj`Adacc9%hu?gYNt$fHBs$rqQBj +nc5flroF'%pgso(SOD5h*S]EkgYNs#gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-598M8*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S]EkgYNt(g`;QB8bcosHN&*_Ae(<$7,-Q=gYNt*hAt/!+S]RJq"t*f!;QW!s8LdP +E;=*qAZ)IigYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Ek +gYNt*(u?:fhAtA-*S]EkgYNt*hAtA-*S]EkgYO_,gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S9!eMMk:*B)[;ZEVO,XV5?H2hAtA-*S]EkgYNt$fHBs$rqQBjnc6#rrmC^\qdq0g +BOnBS2r!10gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAq+#hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Eu*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAt+t+bG>Fph'MYrb_OE(M@AlY-9n?hAtA-*S]EkgYNt*hAt/!+S]RJq"t*^!;HN/s8Kt9 +B_uCkCMRCi]J80t*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Ek +gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-1*,-+*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-)]d\i*S]Ek +gYNt*hAtA-*S]EkgYNstdj'6f=SQM-M#M/dAf>AtA%&m'gYNt*hAtA-*S]EkgYNt*hAt/!+S]RJq"t*^ +!4i./\+jQ!DJiju`%9["*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNs#gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Ek +gYNt*hAtA-%isE]*S]EkgYNsoc6d^X>PMh0MuIDeAfY])@D9N0gYNt*hAtA-*S]EkgYNt*hAtA-*S&db +ph'O#qu?3ejo=!5ri,[)Irf^;aNH!dhAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Ek +gYNt*hAtA-*S]EkgYNt*hF\gChAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Ek +gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNsja9*l2EF/EPrf$Va+E2:,`5a@^hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt$fHBs$rqQBjnc6Q,rqubcph!QPHrqQJSph##+JQ:1M+ktiogYNt*hAtA-*S]Ek +gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]FG*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*Or[9C2.8UB)ZKC +M>:a2Ap\l,cdF&mhAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S&dbph'O#qu?3eaT)82reC2[DMX-G +f%D/"hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Ek?eaEXgYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNsSYr?<.AG^!B)_T&s7-0>s8LFFC\q^nBP:q]ZT$Xq*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Ek +gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-+W]=o*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Ek +gYNr%gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt&g)l63:AAH#J,XK`Ai6?[5MP$8 +gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S&dbph'O#qu?3efDkigrb21@ +/Sf-2\\'ZOhAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAt@#hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Ek +gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Ek+PY`ngYNt*hAtA-*S]Ek +gYNt*hAtA-*S]Eke^kprKN%YXre18gqdqp&B4\3K3SWC2gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]Eke^u#>B)_Q+s8W&tnc7DDrjVZ7Ir9.3_8InZhAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Ek +gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hDlV2hAtA-*S]EkgYNt*hAtA-*S]Ek +gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Ek'\hIbgYNt*hAtA-*S]Ekd*j4eI962UreUPg +qdr$+Bk+Q[1u$k-gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt$ +fHBs$rqQBjnc7MGri,[)7<(gYNt*hAtA-*S]Ek +gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAt/!+S]RJq"t*_!!!#Zs8MrqSG6]G +H$WW=d3RK'*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +:*&*G*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAsVX.<0B7rau%>rf$Va6u[*P`5X=^hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Ek +gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt$fHBs$rqQBjnc7hPrqQJSph!f^JQ:1M+ktiogYNt*hAtA- +*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Ek +gYNt*hAtA-*S]EkgMl!igYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Ek +gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*PfNDD/NeZ +B)ZHBN;.!TFELj2bU;0%*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S&dbph'O#qu?3enGi@brq$,Dph##3M,;dV+5>WmgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Ek +gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]FG*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Ek +gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*P&d;C2.8UB)ZKCM>1ZdH?r`? +d3M-7hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S&dbph'O#qu?3em/R(PrdFQRFcqq\g"[Y'hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Ek +gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAt?QhAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNsUZSuN0AG^!WmgYNt*hAtA-*S]Ek +gYNt*hAtA-*AZC+*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAt/!+S]RJ +q"t*^!:p0hg\u/CB'O!>B)ZoOI/%;POHE2hg`G5,*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S&dbph'O#qu?3ep&G$=rbLA&JS)o6 +rd"KepguCORRPrd*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*?a+n +*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Eke^u#>B)_T&s7-0bs8Kt9BRsdDB$t;jIf=B_Am(n)5MP$8 +gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S&dbph'O#qu?3eq# 0 40 m 0 39 l 120 39 l 120 40 l h W n EOD +nc8IbJS(Hb"+u5VB)H7JUSU30hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Ek +gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S&dbph'O#JcG<@JcC<$JcC<$ +JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$ +JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$ +JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$ +JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcG!7J, +~> restore +14 0 0 25 25 0 cm +save +126 6 cg_miaiproc +38 -37 -36{ +gsave 1 42 div 1 75 div scale 0 exch translate +currentfile 0 (EOD +)/SubFileDecode filter +L3?{flushfile}{cvx exec}ifelse +42 38 scale +BI +/Width 42 +/Height 38 +/BitsPerComponent 8 +/Decode[ +0 1 +0 1 +0 1 +] +/DataSource ImageDataSource +/MaskedImage true +ID +EI +grestore} bind for +0 37 m 0 0 l 42 0 l 42 37 l h W n EOD +JcG]KqZ-V-!eZ,Uqds3=YrCFo*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Eke^u#>AcVT,q"XadqZ-V-!eZ,U +qds3=YrCFo*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Eke^u#>B)_T&s8)fqAcdU;JGWqeYH^%@hAtA-*S]Ek +gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S&dbAnLmOrqQBjqZ-V-!eZ,Uqds3=YrCFo*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]Eke^u#>B)_T&s8)fqAcdU;JGWq]YH^%@hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAldShAt/!+S]RJq"t*g +!<-R3K7e^OAm_aH2r!10gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Ek +gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt$fHBs$rqQBjqZ-V-!eZ,Uqdr^/YrCFo +*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Ek +gYNt*hAtA-*S]EkgC +B)_T&s8)fqAcdU;JGWqcYH^%@hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Ek +gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S&dbph'O#qu?Nnral4aK7Ni2 +6*IOPgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Ek +gYNqkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt$fHBs$rqQBjqZ-V-!eZ,Uqds3=YrCFo*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S]Eke^u#>B)_T&s8)fqAcdU;JGWq=YH^%@hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*SVms*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAt/!+S]RJq"t*g!<-R3K7e^OAm_aH2r!10gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Ek +gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt$fHBs$rqQBjqZ-V- +!eZ,UqdqRdYrCFo*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hCTc&hAtA- +*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S&dbph'O#qu?Nnral4aK7Ni2?a$^ngYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S]EkgYNt*hAt/!+S]RJq"t*g!<-R3K7e^OAgspg2r!10gYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]Ek2;?t.gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S]Eke^u#>B)_T&s8)fqAcdU;JGWqcYH^%@hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Ek +gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S&dbph'O# +qu?Nnral4aK7Ni2+g8.0gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAt?6hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt$fHBs$rqQBjqZ-V-!eZ,Uqds3= +YrCFo*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Eke^u#>B)_T&s8)fqAcdU;JGWprYH^%@hAtA-*S]EkgYNt* +hAtA-*S]EkgYP@>gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAt/!+S]RJq"t*g!<-R3K7e^OAm_aH2r!10gYNt*hAtA-*S]EkgYNt*hAtA-*S]Ek +gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt$ +fHBs$rqQBjqZ-V-!eZ,UqdpGDYrCFo*S]EkgYNt*hAtA-*DP;F*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S&dbph'O#qu?Nnral4a +K7Ni2?a$^ngYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAt/!+S]RJq"t*g!<-R3K7e^OAdPZG2r!10gYNt* +B)_T&s8)fqAcdU;JGWqcYH^%@hAtA-*S]EkgYNt*hAtA-*S]Ek +gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S&dbph'O#qu?Nnral4aK7Ni2!O&b62r!10gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt$fHBs$rqQBj +qZ-V-!eZ,Uqds3=YrCFo*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Eke^u#>B)_T&s8)fqAcdU;JGWqcYH^%@ +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S&dbph'O#qu?Nnral4aK7Ni2?a$^ngYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAt/!+S]RJq"t*i!!*'"ral4aK7Ni2?a$^ngYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAt/! ++S]RJq"t*g!<-R3K7e^OAm_aH2r!10gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt$fHBs$rqHNos8Dup!<-R3 +K7e^OAm_aH2r!10gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt$fHBs$rqQBjqZ-V-!eZ,Uqds3=YrCFo*S]Ek +gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]Eke^u#AB)ZEAq"t*g!<-R3K7e^OAm_aH2r!10gYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt$fHBs$rqQBjqZ-V-!eZ,Uqds-;YrCFo*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkeH+;Fph'O# +qu?Nnral4aK7Ni2?a$^ngYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Ek +gYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAt/!+S]RJq"t)A +~> 0 38 m 0 0 l 42 0 l 42 38 l h W n EOD +qZ-V-!eZ,Uqds3=YrCFo*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Eke^u#>B)_T&s8)fqAcdU;JGWqcYH^%@ +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S&dbpgsO$!VlHes8)fqAcdU;JGWqcYH^%@hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S&dbph'O#qu?Nnral4aK7Ni2@BZppgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAt(r ++_G?_B)_T&s8)fqAcdU;JGWqcYH^%@hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAt+t+bbYKph'O#qu?Nnral4a +K7Ni2=g,(hgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkcHmj=H@&fiB)[nkrql`m!<-R3K7e^OAm)=B2r!10gYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAsSV.WTQ9ph'N!rr)WlqZ-V-!eZ,Uqdr^/YrCFo*S]EkgYNt*hAtA-*S]EkgYNt*hAtA- +*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]Ek]*,f$Ci!PTB)].- +s8)fqAcdU;JGWqWYH^%@hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hArc'3+uu9qe#hArl4F,qZ-V-!eZ,UqdrF'YrCFo*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*h?+dl +U-\Qdrbqefm/Qq_ral4aK7Ni29!>KYgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAt8'*g2^Zph'MLroE>DqZ-V-!eZ,Uqdr-tYrCFo*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*S]EkgYNt*hAtA-*gYNt*hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*S]EkgYNt$f-#g&;>=c&K)Y5as8)fqAcdU;JGWq%YH^%@hAtA-*S]EkgYNt* +hAtA-*S]EkgYNt*hAtA-*SUqX*S]EkcI!naHs$/Urf@'QbQ%G>ral4aK7Ni2.Bg!8gYNt*hAtA-*S]Ek +gYNt*hAtA-*S]EkgYNt*hAtA-*QH/LEcYO]B)\J&r5ep8!<-R3K7e^OAf7eW2r!10gYNt*hAtA-*S]Ek +gYNt*hAtA-$m"*Z*S]Ek]Y6(9Cgm*Nrj'E@qZ-V-!eZ,Uqdq(VYrCFo*S]EkgYNt*hAtA-*S]EkgYNt* +hAtA-*Nu_,BP:rRB)ZND`P;HM!<-R3K7e^OAeD5O2r!10gYNt*hAtA-*S]Ek$esMYgYNt*hAr;b5knsj +DZ85"s8)fqAcdU;JGWpsYH^%@hAtA-*S]EkgYNt*hAtA-*SK3hP*AQ5B)[#RjLP 0 38 m 0 36 l 42 36 l 42 38 l h W n EOD +qZ-V-!fDkirmcu-qZ$]=aL_B6OoL"4JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$ +JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$JcC<$l2Q8 +~> restore +ep +end +%%Trailer +%%EOF diff --git a/img/保存.png b/img/保存.png new file mode 100644 index 0000000..031ebb6 Binary files /dev/null and b/img/保存.png differ diff --git a/img/保存占用.png b/img/保存占用.png new file mode 100644 index 0000000..af529f2 Binary files /dev/null and b/img/保存占用.png differ diff --git a/img/保存弹窗.png b/img/保存弹窗.png new file mode 100644 index 0000000..031ebb6 Binary files /dev/null and b/img/保存弹窗.png differ diff --git a/img/保存标签.png b/img/保存标签.png new file mode 100644 index 0000000..09a6003 Binary files /dev/null and b/img/保存标签.png differ diff --git a/img/保存表单项.png b/img/保存表单项.png new file mode 100644 index 0000000..77d2d04 Binary files /dev/null and b/img/保存表单项.png differ diff --git a/img/修改标签.png b/img/修改标签.png new file mode 100644 index 0000000..cabac96 Binary files /dev/null and b/img/修改标签.png differ diff --git a/img/修改表单项.png b/img/修改表单项.png new file mode 100644 index 0000000..4dc44bd Binary files /dev/null and b/img/修改表单项.png differ diff --git a/img/创建文件.png b/img/创建文件.png new file mode 100644 index 0000000..5db7844 Binary files /dev/null and b/img/创建文件.png differ diff --git a/img/创建目录项.png b/img/创建目录项.png new file mode 100644 index 0000000..7bacfbf Binary files /dev/null and b/img/创建目录项.png differ diff --git a/img/删除.png b/img/删除.png new file mode 100644 index 0000000..41587da Binary files /dev/null and b/img/删除.png differ diff --git a/img/取消弹窗.png b/img/取消弹窗.png new file mode 100644 index 0000000..657c8f7 Binary files /dev/null and b/img/取消弹窗.png differ diff --git a/img/弹窗关闭.png b/img/弹窗关闭.png new file mode 100644 index 0000000..99e5349 Binary files /dev/null and b/img/弹窗关闭.png differ diff --git a/img/弹窗背景.png b/img/弹窗背景.png new file mode 100644 index 0000000..b108b71 Binary files /dev/null and b/img/弹窗背景.png differ diff --git a/img/文件校验.png b/img/文件校验.png new file mode 100644 index 0000000..826c4ed Binary files /dev/null and b/img/文件校验.png differ diff --git a/img/查询.png b/img/查询.png new file mode 100644 index 0000000..5e3282c Binary files /dev/null and b/img/查询.png differ diff --git a/img/校验.png b/img/校验.png new file mode 100644 index 0000000..f9aa602 Binary files /dev/null and b/img/校验.png differ diff --git a/img/校验2.png b/img/校验2.png new file mode 100644 index 0000000..e04acb6 Binary files /dev/null and b/img/校验2.png differ diff --git a/img/消息框背景 (1).png b/img/消息框背景 (1).png new file mode 100644 index 0000000..70b9826 Binary files /dev/null and b/img/消息框背景 (1).png differ diff --git a/img/消息框背景 (3).png b/img/消息框背景 (3).png new file mode 100644 index 0000000..6055fe3 Binary files /dev/null and b/img/消息框背景 (3).png differ diff --git a/img/消息框背景 (5).png b/img/消息框背景 (5).png new file mode 100644 index 0000000..8b1f410 Binary files /dev/null and b/img/消息框背景 (5).png differ diff --git a/img/添加占用.png b/img/添加占用.png new file mode 100644 index 0000000..f776c49 Binary files /dev/null and b/img/添加占用.png differ diff --git a/img/清除标签.png b/img/清除标签.png new file mode 100644 index 0000000..40edffe Binary files /dev/null and b/img/清除标签.png differ diff --git a/img/清除目录项.png b/img/清除目录项.png new file mode 100644 index 0000000..bcfa2f1 Binary files /dev/null and b/img/清除目录项.png differ diff --git a/img/清除表单项.png b/img/清除表单项.png new file mode 100644 index 0000000..7310295 Binary files /dev/null and b/img/清除表单项.png differ diff --git a/img/编组 5.png b/img/编组 5.png new file mode 100644 index 0000000..d1a283a Binary files /dev/null and b/img/编组 5.png differ diff --git a/img/编辑.png b/img/编辑.png new file mode 100644 index 0000000..a6a1b7c Binary files /dev/null and b/img/编辑.png differ diff --git a/img/重置.png b/img/重置.png new file mode 100644 index 0000000..708c046 Binary files /dev/null and b/img/重置.png differ diff --git a/output.bin b/output.bin new file mode 100644 index 0000000..c39f990 Binary files /dev/null and b/output.bin differ diff --git a/read_bin.py b/read_bin.py new file mode 100644 index 0000000..815c1a1 --- /dev/null +++ b/read_bin.py @@ -0,0 +1,104 @@ +# -*- encoding: utf-8 -*- +""" +@File : read_bin.py +@License : (C)Copyright 2021-2023 + +@Modify Time @Author @Version @Description +------------ ------- -------- ----------- +2023/10/9 16:27 zart20 1.0 None +""" +# SECTOR_SIZE = 512 # 扇区大小 +# BYTES_PER_LINE = 16 # 每行字节数 +# # MAX_SECTORS_TO_READ = 15927 # 要读取的最大扇区数量 +# MAX_SECTORS_TO_READ = 0 +# # 打开设备文件 +# # drive_letter = "I:" # 请替换为你要操作的磁盘 +file_path = f"output.bin" # 设备文件路径 +# +# try: +# with open(file_path, 'rb') as disk: +# sector_number = 0 # 起始扇区号 +# byte_offset = 0 # 字节偏移量初始化 +# sectors_read = 0 # 已读取的扇区数量 +# +# while sectors_read <= MAX_SECTORS_TO_READ: +# # 读取扇区数据 +# disk.seek(sector_number * SECTOR_SIZE) +# sector_data = disk.read(SECTOR_SIZE) +# +# # 输出扇区数据 +# print(f"扇区号:{sector_number}") +# for i in range(0, len(sector_data), BYTES_PER_LINE): +# line_data = sector_data[i:i + BYTES_PER_LINE] +# print(f"{byte_offset + i:08X}:", end=" ") # 输出字节偏移量(16进制) +# for byte in line_data: +# print(f"{byte:02X}", end=" ") # 输出每个字节的16进制表示 +# +# print() # 换行 +# +# # 更新扇区号,读取下一个扇区 +# sector_number += 1 +# byte_offset += len(sector_data) # 累加字节偏移量 +# sectors_read += 1 +# +# except PermissionError: +# print("没有足够的权限来访问磁盘。请以管理员身份运行程序。") +# except FileNotFoundError: +# print(f"找不到设备文件:{file_path}") +# except Exception as e: +# print(f"发生错误:{e}") + + +def read_sector_0(): + SECTOR_SIZE = 512 # 扇区大小 + BYTES_PER_LINE = 16 # 每行字节数 + SECTORS = 0 + with open(file_path, 'rb') as disk: + disk.seek(SECTORS *SECTOR_SIZE) + sector_data = disk.read(SECTOR_SIZE) + # for i in range(0, len(sector_data), BYTES_PER_LINE): + # line_data=sector_data[i:i+BYTES_PER_LINE] + # print(f"{SECTORS*32+i:08X}:", end=" ") + # for byte in line_data: + # print(f"{byte:02X}", end=" ") + # disk_dict[f"{i:08X}:"].append(f"{byte:02X}") + # print() + return SECTORS, sector_data + +def read_sector_FAT1(): + SECTOR_SIZE = 512 # 扇区大小 + BYTES_PER_LINE = 16 # 每行字节数 + SECTORS = 34 + with open(file_path, 'rb') as disk: + disk.seek(SECTORS *SECTOR_SIZE) + sector_data = disk.read(SECTOR_SIZE) + # for i in range(0, len(sector_data), BYTES_PER_LINE): + # line_data=sector_data[i:i+BYTES_PER_LINE] + # print(f"{SECTORS*32+i:08X}:", end=" ") + # for byte in line_data: + # print(f"{byte:02X}", end=" ") + # disk_dict[f"{i:08X}:"].append(f"{byte:02X}") + # print() + return SECTORS, sector_data + +def read_sector_root_path(num): + SECTOR_SIZE = 512 # 扇区大小 + BYTES_PER_LINE = 16 # 每行字节数 + SECTORS = 15032+num + with open(file_path, 'rb') as disk: + disk.seek(SECTORS *SECTOR_SIZE) + sector_data = disk.read(SECTOR_SIZE) + # for i in range(0, len(sector_data), BYTES_PER_LINE): + # line_data=sector_data[i:i+BYTES_PER_LINE] + # print(f"{SECTORS*32+i:08X}:", end=" ") + # for byte in line_data: + # print(f"{byte:02X}", end=" ") + # print(f"{chr(byte)}", end="") + # print() + # print(sector_data) + return SECTORS, sector_data + +if __name__ == '__main__': + read_sector_0() + read_sector_FAT1() + read_sector_root_path(0) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..5a11983 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +numpy==1.26.0 +Pillow==10.0.1 diff --git a/run_test.py b/run_test.py new file mode 100644 index 0000000..e69de29 diff --git a/test.py b/test.py new file mode 100644 index 0000000..8d63733 --- /dev/null +++ b/test.py @@ -0,0 +1,87 @@ +# -*- encoding: utf-8 -*- +""" +@File : test.py +@License : (C)Copyright 2021-2023 + +@Modify Time @Author @Version @Description +------------ ------- -------- ----------- +2023/10/7 11:20 zart20 1.0 None +""" +char = "A" + +hex_value = hex(ord(char)) + +print(f"The hexadecimal value of '{char}' is {hex_value}") + +def char_to_hex(st): + hex_value = hex(ord(st)) + print(f"The hexadecimal value of '{st}' is {hex_value}") + +def hex_to_char(hex): + char = chr(int(hex, 16)) + print(f"The character represented by '{hex}' is '{char}'") + + + + + +""" +真实磁盘的读写,以标称64GB的U盘为例,查看磁盘记录信息的工具是WinHex +将一块64GB的U盘接入电脑,为了方便查看结果,先将用磁盘工具如DiskGenius将U盘格式化, +注意格式化时文件系统选择FAT32,簇大小选择64KB +此时用管理员权限打开WinHex + + +""" + +import pandas as pd + +# 创建一个空的DataFrame +df = pd.DataFrame(columns=["Name", "Age"]) + +# 创建一个字典 +new_data = {"Name": "John", "Age": 30} + +# 使用append方法将字典添加到DataFrame中 +df = df.add + +# 打印DataFrame +print(df) + + +import tkinter as tk +import tkinter.font as tkFont + +def open_file(): + # 在这里添加打开文件的功能 + pass + +def save_file(): + # 在这里添加保存文件的功能 + pass + +def exit_app(): + root.quit() + +root = tk.Tk() +root.title("菜单栏字体大小示例") + +# 创建自定义字体 +custom_font = tkFont.Font(family="Helvetica", size=16) # 修改字体和大小 + +# 创建菜单栏 +menubar = tk.Menu(root, font=custom_font) +root.config(menu=menubar) + +# 创建文件菜单 +file_menu = tk.Menu(menubar, tearoff=0, font=custom_font) +menubar.add_cascade(label="文件", menu=file_menu) + +# 在文件菜单中添加选项 +file_menu.add_command(label="打开", command=open_file) +file_menu.add_command(label="保存", command=save_file) +file_menu.add_separator() +file_menu.add_command(label="退出", command=exit_app) + +# 运行主循环 +root.mainloop() diff --git a/time_jx.py b/time_jx.py new file mode 100644 index 0000000..d36d4af --- /dev/null +++ b/time_jx.py @@ -0,0 +1,45 @@ +# -*- encoding: utf-8 -*- +""" +@File : time_jx.py +@License : (C)Copyright 2021-2023 + +@Modify Time @Author @Version @Description +------------ ------- -------- ----------- +2023/10/10 14:30 zart20 1.0 None +""" +# 时间解析 +def time_parse(time_bytes): + # 从两个字节中解析时间信息 + time_bytes = b'\x29\x8B' # 用于演示的两个字节数据 + raw_time_value = int.from_bytes(time_bytes, byteorder='little') # 将两个字节合并为一个整数 + + # 提取小时、分钟和秒 + hour = (raw_time_value >> 11) & 0x1F # 前11位表示小时 + minute = (raw_time_value >> 5) & 0x3F # 接下来的5位表示分钟 + second = (raw_time_value & 0x1F) * 2 # 最后的5位表示秒,以2秒的粒度存储 + + print(f"{hour}:{minute}:{second}") + + +def date_parse(date_bytes): + import datetime + date_bytes = b'\x47\x57' # 用于演示的两个字节数据 + raw_date_value = int.from_bytes(date_bytes, byteorder='little') # 将两个字节合并为一个整数 + + # 提取年份、月份和日期字段 + year_offset = (raw_date_value >> 9) & 0x7F # 取前7位作为年份的偏移值 + month = (raw_date_value >> 5) & 0x0F # 取接下来的4位作为月份 + day = raw_date_value & 0x1F # 取最后的5位作为日期 + + # 计算实际年份 + year = 1980 + year_offset + + # 创建日期对象 + date = datetime.date(year, month, day) + + # 打印可读的日期表示 + print("日期:", date.strftime("%Y-%m-%d")) + +if __name__ == '__main__': + time_parse(b'\x29\x8B') + date_parse(b'\x47\x57') \ No newline at end of file