def test_can_order_layers_for_rendering(self): kwargs = { "left": SA("parent.left"), "right": SA("parent.right"), "top": SA("parent.top"), "bottom": SA("parent.bottom") } l1 = ColorLayer("layer_1", content="#FF0000", order=1, **kwargs) l2 = ColorLayer("layer_1", content="#00FF00", order=2, **kwargs) temp = Template("temp", l1, l2, left=NA(0), width=NA(50), top=NA(0), height=NA(50)) temp.update_bounds() green_above = temp.render() color_of_top_left_most_pixel = green_above.export_pixels(width=1, height=1) # RGBA, [1] is green assert color_of_top_left_most_pixel[:3] == [0, 255, 0] l1.order = 3 # move red above red_above = temp.render() color_of_top_left_most_pixel = red_above.export_pixels(width=1, height=1) assert color_of_top_left_most_pixel[:3] == [255, 0, 0]
def test_can_make_a_text_layer_without_content(self): l = PointTextLayer("layer", "Arial", 12, "Black", left=NA(30), top=NA(45))
def point_text_layer(self): return PTL("area_text_layer", "Arial", 12, "Black", content="test", left=NA(0), bottom=NA(50))
def test_can_update_y_bounds(self): layer = self.area_text_layer() temp = Template("temp", layer, left=NA(0), width=NA(50), top=NA(0), height=NA(50)) layer.y.update_bounds()
def area_text_layer(self): return AreaTextLayer("area_text_layer", "Arial", 12, "Black", left=NA(0), width=NA(40), bottom=NA(50), height=NA(50))
def test_a_text_layer_requires_1_x_y_coord(self): with pytest.raises(ValueError): PointTextLayer("layer", "Arial", 12, "Black") PointTextLayer("layer", "Arial", 12, "Black", left=NA(40), XP30=NA(20))
def test_can_update_y_bounds_when_attributes_are_evaluatable_and_content_is_set( self): layer = self.point_text_layer() temp = Template("temp", layer, left=NA(0), width=NA(50), top=NA(0), height=NA(50)) layer.y.update_bounds()
def test_idm_works_for_text_layer_without_content(self): bg = ColorBackgroundLayer("bg", content="White") # content is None layer = PointTextLayer("layer", "Arial", 12, "Black", left=NA(0), base=NA(40)) square = ColorLayer("sqr", content="Red", width=NA(20), height=NA(20), bottom=SA("layer.cap"), left=NA(25)) temp = Template("temp", layer, square, bg, left=NA(0), width=NA(50), top=NA(0), height=NA(50)) temp.update_bounds() temp.render().save( filename= "tests/images/test_idm_works_for_text_layer_without_content.png")
def test_can_have_templates_within_templates(self): pt = PointTextLayer("point_text_layer", content="Point Text Layer", font="Arial", size=35, color="Black", left=NA(0), top=NA(0)) bg = ColorLayer("bg", content="Red", left=NA(0), width=SA("parent.width"), height=SA("parent.height"), top=NA(0)) temp = Template("temp", pt, bg, left=NA(0), right=SA("point_text_layer.right"), top=NA(0), height=NA(100)) temp2 = Template("temp", temp, left=NA(0), right=SA("point_text_layer.right"), top=NA(0), height=NA(500)) temp2.update_bounds()
def test_template_can_render_boundary(self): pt = PointTextLayer("pt", "Arial", 15, "Black", content="Hello World", left=NA(0), top=NA(0)) square = ColorLayer("square", content="Orange", left=NA(20), top=NA(20), height=NA(20), width=NA(20)) bg = ColorBackgroundLayer("bg", content="None") temp = Template("temp", pt, square, bg, left=NA(0), width=NA(100), top=NA(0), height=NA(100)) temp.update_bounds() boundary = temp.render_boundary() # boundary.save(filename="tests/images/test_template_can_render_boundary_b.png") image = temp.render()
def test_can_unset_attributes_evaluated_values(self): """Because the content of pt is changing per iteration, the left of square should change as well (top should change due to p in people).""" content_list = ["hello world", "people"] square_lefts = [] # stores left values per iteration square_tops = [] pt = PTL("pt", "Arial", 15, "Black", left=NA(0), top=NA(0)) square = ColorLayer("square", content="Red", left=AA(SA("pt.right")), top=SA("pt.bottom"), width=NA(20), height=NA(20)) bg = ColorBackgroundLayer("bg", content="White") temp = Template("temp", pt, square, bg, left=NA(0), top=NA(0), height=NA(100), width=NA(100)) for i, content in enumerate(content_list): pt.pre_render = None pt.content = content temp.unset_bounds_and_attributes() temp.update_bounds() temp.render().save( filename= f"tests/images/{i}_test_can_unset_attributes_evaluated_values.png" ) square_lefts.append(temp.get_layer("square")["left"]) square_tops.append(temp.get_layer("square")["top"]) assert square_lefts[0] != square_lefts[1] assert square_tops[0] != square_tops[1]
def test_can_render_shadow(self): pt = PTL("pt", "Arial", 15, "Black", content="PT", left=NA(0), top=NA(0)) pt2 = PTL("pt2", "Arial", 15, "Black", content="PT2", left=NA(0), top=AA(SA("pt.bottom"), NA(5))) bg = ColorBackgroundLayer("bg", content="White") temp = Template("temp", pt, pt2, bg, left=NA(0), width=NA(50), top=NA(0), height=NA(50)) temp.update_bounds() image = temp.render() image.save(filename="tests/images/test_can_render_shadow_1.png") shadow = pt2.shadow(2, 2, radius=4, sigma=2) image.composite(shadow, 0, 0) image.save(filename="tests/images/test_can_render_shadow_2.png")
def test_can_render_color_overlay(self): pt = PTL("pt", "Arial", 15, "Black", content="PT", left=NA(0), top=NA(0)) pt2 = PTL("pt2", "Arial", 15, "Black", content="PT2", left=NA(0), top=AA(SA("pt.bottom"), NA(5))) bg = ColorBackgroundLayer("bg", content="Red") temp = Template("temp", pt, pt2, bg, left=NA(0), width=NA(50), top=NA(0), height=NA(50)) temp.update_bounds() image = temp.render() image.save(filename="tests/images/test_can_render_color_overlay_1.png") overlay = pt2.color_overlay("Blue") image.composite(overlay, int(pt2["left"]), int(pt2["top"])) image.save(filename="tests/images/test_can_render_color_overlay_2.png")
def test_template_with_add_attribute_can_render(self): title = PTL("title", "Arial", 15, "Black", content="Hello World", left=NA(0), top=NA(0)) sub_title = PTL("sub_title", "Arial", 15, "Black", content="Bottom Text", left=NA(10), bottom=AA(SA("template.height"), NA(45, negative=True))) bg = ColorBackgroundLayer("bg", content="White") temp = Template("temp", title, sub_title, bg, left=NA(0), top=NA(0), width=NA(200), height=NA(200)) temp.update_bounds() image = temp.render() image.save( filename= f"tests/images/test_template_with_add_attribute_can_render.jpg")
def test_can_make_a_text_layer_with_percent_bounds(self): l = PointTextLayer("layer", "Arial", 12, "Black", YP40=NA(30), XP50_50=SA("title.left"))
def test_cannot_make_text_layer_with_bad_coords(self): with pytest.raises(ValueError): PointTextLayer("layer", "Arial", 12, "Black", test=SA("parent.height"), wow=NA(12))
def update_bounds(self, **kwargs): if not self.is_bounded: if self.amount == 1: # is a point layer full = next(key for key, value in self.mapping.items() if value == 'full') if self.layer.content is None: self.attributes[full] = NA(0) else: self.attributes[full] = NA( getattr(self.layer.render(), full)) try: bounds = self.attributes_to_bounds() self.bounds = Bounds(**bounds, **kwargs) return self.bounds except NotEvaluatedError: pass else: return self.bounds
def test_setting_base_on_ptl_is_same_as_drawing_text(self): width = 100 text = "Hpqrs" left = 0 base = 20 median = 40 median_offset_for_font_size_12 = 6 bg_color = "White" bg = ColorBackgroundLayer("bg", content=bg_color) l = PointTextLayer("l", "Arial", 12, "Black", content=text, left=NA(left), base=NA(base)) l2 = PointTextLayer("l2", "Arial", 12, "Black", content=text, left=NA(left), median=NA(median)) temp = Template("temp", l, l2, bg, left=NA(0), right=NA(width), top=NA(0), bottom=NA(width)) temp.update_bounds() img = temp.render() img.save( filename= "tests/images/test_setting_base_on_ptl_is_same_as_drawing_text.png" ) with nested( Image(width=width, height=width, background=Color(bg_color)), Drawing()) as (img2, draw): draw.font = l.font draw.font_size = l.size draw.text(left, base, text) draw.text(left, median + median_offset_for_font_size_12, text) draw(img2) img2.save( filename= "tests/images/test_setting_base_on_ptl_is_same_as_drawing_text_2.png" ) location, diff = img.similarity(img2, metric="absolute") assert diff == 0
def test_can_make_negative_numeric_attribute(self): """Tests if negative NAs can be initialised and if the different conventions will produce the same result""" negative_num_attr_1 = NA(-30) negative_num_attr_2 = NA(30, True) # test_layer_1 and test_layer_2 will have same left value title = PTL("title", "Arial", 15, "Black", content="Hello World", left=NA(0), top=NA(0)) test_layer_1 = ColorLayer("test_layer_1", content="Blue", left=negative_num_attr_1, right=SA("parent.right"), top=SA("title.top"), height=NA(20)) test_layer_2 = ColorLayer("test_layer_2", content="Green", left=negative_num_attr_2, right=SA("parent.right"), top=SA("test_layer_1.top"), height=NA(20)) temp = Template("temp", title, test_layer_1, test_layer_2, left=NA(0), width=NA(100), top=NA(0), height=NA(100)) temp.update_bounds() assert test_layer_1["left"] == test_layer_2["left"]
def test_layers_passed_in_first_without_order_are_rendered_first( self, save_images): kwargs = { "left": SA("parent.left"), "right": SA("parent.right"), "top": SA("parent.top"), "bottom": SA("parent.bottom") } l1 = ColorLayer("layer_1", content="#FF0000", **kwargs) # red l2 = ColorLayer("layer_1", content="#00FF00", **kwargs) # green # l1 is first, is rendered first; therefore l2 (green) should be on top temp = Template("temp", l1, l2, left=NA(0), width=NA(50), top=NA(0), height=NA(50)) temp.update_bounds() green_above = temp.render() color_of_top_left_most_pixel = green_above.export_pixels(width=1, height=1) assert color_of_top_left_most_pixel[:3] == [0, 255, 0] # RGBA, [1] is green # remake template, now l2 is first, l1 rendered last temp = Template("temp", l2, l1, left=NA(0), width=NA(50), top=NA(0), height=NA(50)) temp.update_bounds() red_above = temp.render() color_of_top_left_most_pixel = red_above.export_pixels(width=1, height=1) assert color_of_top_left_most_pixel[:3] == [255, 0, 0] if save_images: green_above.save(filename="tests/images/green_above.png") red_above.save(filename="tests/images/red_above.png")
def test_this_configuration_can_render(self): pt = PointTextLayer("ptl", "Arial", 15, "Black", content="Hello World", left=AA(SA("parent.left"), NA(5)), top=SA("parent.top")) bg = ColorBackgroundLayer("bg", content="Green") temp = Template("temp", pt, bg, left=NA(10), right=SA("ptl.right"), top=SA("parent.top"), height=NA(100)) temp2 = Template("temp2", temp, left=NA(0), right=NA(100), top=NA(0), height=NA(100)) temp2.update_bounds() image = temp2.render()
def test_template_variable_get_set_correctly(self): pt = PointTextLayer("ptl", "Arial", 15, "Black", content="Hello World", left=AA(SA("parent.left"), NA(5)), top=SA("parent.top")) bg = ColorBackgroundLayer("bg", content="Green") temp = Template("temp", pt, bg, left=NA(10), right=SA("ptl.right"), top=SA("parent.top"), height=NA(100)) temp2 = Template("temp2", temp, left=NA(0), right=NA(100), top=NA(0), height=NA(100)) assert pt.template == bg.template assert pt.parent == temp assert pt.template == temp2 assert pt.template == temp.template
def test_can_get_mean_indepth_font_metrics_for_ptl(self): bg = ColorBackgroundLayer("bg", content="White") l = PointTextLayer("l", "Arial", 12, "Black", content="Hpqrs", left=NA(0), base=NA(20)) l2 = PointTextLayer("l2", "Arial", 12, "Black", content="e", left=NA(10), median=NA(50)) # l3 = PointTextLayer("l3", "Arial", 12, "Black", content="l", left=NA(20), descender=NA(50)) l4 = PointTextLayer("l4", "Arial", 12, "Black", content="l", left=NA(30), cap=NA(50)) # l5 = PointTextLayer("l5", "Arial", 12, "Black", content="o", left=NA(40), ascender=NA(50)) temp = Template( "temp", l, l2, bg, left=NA(0), # temp = Template("temp", l, l2, l3, l4, l5, left=NA(0), # right=SA("l5.right"), top=NA(0), bottom=SA("l5.bottom")) right=SA("l.right"), top=NA(0), bottom=SA("l.bottom")) temp.update_bounds() temp.render().save( filename= "tests/images/test_can_get_mean_indepth_font_metrics_for_ptl.png")
def test_point_text_layer_can_render_when_content_and_parent_is_set(self): l = PointTextLayer("layer", "Arial", 12, "Black", content="hello world", left=NA(30), top=NA(45)) temp = Template("temp", l, left=NA(0), width=NA(50), top=NA(0), height=NA(50)) temp.update_bounds() l.render() assert l.pre_render is not None
image = Image(width=int(self["width"]), height=int(self["height"])) for layer in sorted(self.layers, key=lambda l: l.order): if layer.content is not None or isinstance(layer, Template): img = layer.render(fresh) if img is not None: image.composite(img, left=int(layer["left"] - self["left"]), top=int(layer["top"]- self["top"])) return image if __name__ == "__main__": # color = ColorLayer("color", content="Red", left=AA(SA('-parent.left'), NA(100)), width=NA(300), # top=AA(SA('-parent.top'), NA(100)), height=NA(500)) # bg = ColorBackgroundLayer("bg", content="White") # mask_bg = ColorBackgroundLayer("bg", content="Green") # mask = Template("mask", color, mask_bg, left=NA( # 200), width=NA(200), top=NA(100), height=NA(300)) # temp = Template("main", mask, bg, left=NA( # 0), width=NA(500), top=NA(0), height=NA(700)) color2 = ColorLayer("color", content="Red", left=NA(100), width=NA(300), top=NA(100), height=NA(500)) bg2 = ColorBackgroundLayer("bg", content="White") mask_bg2 = ColorBackgroundLayer("bg", content="Green") mask2 = Mask("mask", color2, mask_bg2, left=NA(200), width=NA(200), top=NA(100), height=NA(300)) temp2 = Template("main", mask2, bg2, left=NA(0), width=NA(500), top=NA(0), height=NA(700)) temp2.update_bounds() image = temp2.render() image.save(filename="test.png")
def make(self, card): art_layers, llayers = self.layers(card) text_template = Template("text_temp", *llayers, left=NA(0), width=NA(self.WIDTH), top=NA(0), height=NA(self.HEIGHT)) art_template = Template("art_temp", *art_layers, order=-5, left=NA(0), width=NA(self.WIDTH), top=NA(0), height=NA(self.HEIGHT)) temp = Template("template", text_template, art_template, left=NA(0), width=NA(self.WIDTH), top=NA(0), height=NA(self.HEIGHT)) # generic templating temp.mana_image_format = "svg" temp.resource_dir = self.RESOURCE_DIR # START setting content rules = self.getRules(card) temp.get_layer("rules").content = rules for name in temp.get_layer("text_temp").layers: layer = temp.get_layer(name) if layer.name in card: layer.content = card[layer.name] if card['flavor_name'] is not None: temp.get_layer('name').content = card['flavor_name'] temp.get_layer('flavor_name').content = card['name'] # card['name'], card['flavor_name'] = card['flavor_name'], card['name'] if card["layout"] == "adventure": for cc in card['card_faces']: if "power" in cc: creature = cc else: adventure_card = cc temp.get_layer('name').content = creature['name'] temp.get_layer('mana_cost').content = creature['mana_cost'] temp.get_layer('type').content = creature['type_line'] temp.get_layer( "adventure_rules").content = adventure_card['oracle_text'] temp.get_layer( "adventure_type").content = adventure_card["type_line"] temp.get_layer("adventure_name").content = adventure_card["name"] temp.get_layer( "adventure_mana_cost").content = adventure_card["mana_cost"] elif card["layout"] == "split": temp.get_layer("name").content = card["card_faces"][0]["name"] temp.get_layer("type").content = card["card_faces"][0]["type_line"] temp.get_layer( "mana_cost").content = card["card_faces"][0]["mana_cost"] temp.get_layer( "rules").content = card["card_faces"][1]["oracle_text"] temp.get_layer("split_art_top" ).content = card["card_faces"][0]["image_location"] temp.get_layer("split_art_bottom" ).content = card["card_faces"][1]["image_location"] temp.get_layer( "split_name").content = card["card_faces"][1]["name"] temp.get_layer( "split_mana_cost").content = card["card_faces"][1]["mana_cost"] temp.get_layer( "split_type").content = card["card_faces"][0]["type_line"] temp.get_layer( "split_rules").content = card["card_faces"][0]["oracle_text"] # generic if "Creature" in card["type"]: temp.get_layer( "PT").content = f"{card['power']}/{card['toughness']}" number = card['number'].upper().zfill(3) count = int(card['count']) temp.get_layer("number").content = f"{number}/{count:03}" rarity = card["rarity"][0].upper() temp.get_layer("rarity").color = self.rarity_colors[rarity] temp.get_layer("rarity").content = rarity # RULES CONTENT # if rules != "": # else: # temp.get_layer('rules').content = card[self.text_to_use] art_path = join(self.RESOURCE_DIR, "art", card['set'], f"{card['name']}_{card['id']}.jpg") \ .replace("//", "__") # print(art_path) if card['image_location']: temp.get_layer("art").content = card['image_location'] else: temp.get_layer("art").content = art_path if os.path.isfile( art_path) else None # generic temp.update_bounds() render_bg = temp.get_layer("art_temp").render() image = render_bg.clone() # if temp.get_layer("art").content is not None: render_text_shadow = temp.get_layer("text_temp").shadow(-4, 4, sigma=2, radius=4, color="Black") image.composite(render_text_shadow, left=0, top=0) render_text = temp.get_layer("text_temp").render() image.composite(render_text, left=0, top=0) # END setting content # SAVING content # image.save(filename=join(SAVE_LOCATION, f"{card['name']}_{card['id']}.jpg").replace("//", "__")) # image.save(filename=join(SAVE_LOCATION, f"{card['name']}.jpg").replace("//", "__")) p = self.pdf.clone() p.composite(image, left=73, top=67) p.save(filename=join(self.PDF_SAVE_LOCATION, f"{card['name']}_{card['id']}.pdf").replace( "//", "__"))
def __init__(self, deckName): self.RESOURCE_DIR = join(os.getcwd(), "resources") # self.TEST_DIR = "test_images" # FONTS self.MPLANTIN = join(self.RESOURCE_DIR, "fonts", "MPlantin.ttf") self.BELEREN_SC = join(self.RESOURCE_DIR, "fonts", "Beleren_small_caps.ttf") self.BELEREN = join(self.RESOURCE_DIR, "fonts", "Jace_Beleren_bold.ttf") self.MPLANTIN_BOLD = join(self.RESOURCE_DIR, "fonts", "MPlantin_bold.ttf") self.MPLANTIN_ITAL = join(self.RESOURCE_DIR, "fonts", "MPlantin_italic.ttf") self.RELAY = join(self.RESOURCE_DIR, "fonts", "Relay_medium.ttf") self.FC = "White" self.FLAVOR_SPLIT_COLOR = "RGBA(255, 255, 255, 0.6)" self.SHADOW_COLOR = "#181510" self.FLAVOR_SPLIT_OFFSET = 40 self.SET_DOT_LANG_WIDTH = 5 self.INFO_SIZE = 18 self.NAME_SIZE = 38 self.FLAVOR_NAME_SIZE = 25 self.TYPE_SIZE = 33 self.PT_LOYAL_SIZE = 40 self.RULES_TEXT_SIZE = 25 self.INNER_BORDER = 40 self.INNER_RULES_BORDER = 50 self.INNER_HEIGHT = 1040 self.INNER_WIDTH = 745 self.HEIGHT = 1080 self.WIDTH = 773 self.SPLIT_CENTER = 460 self.SPLIT_END = 870 self.SPLIT_HEIGHT = self.SPLIT_END - self.SPLIT_CENTER self.SPLIT_SHADOW_SIZE = 50 self.OUTER_X_BORDER = (self.WIDTH - self.INNER_WIDTH) / 2 self.TOTAL_Y_BORDER = (self.HEIGHT - self.INNER_HEIGHT) self.OUTER_Y_BOTTOM_BORDER = 21 self.TOP_OUTER_BORDER = 20 self.STANDARD_BORDER = 40 self.BORDER = self.STANDARD_BORDER + self.OUTER_X_BORDER self.TOP_BORDER = self.STANDARD_BORDER + self.TOP_OUTER_BORDER self.BOTTOM_BORDER = self.STANDARD_BORDER + self.OUTER_Y_BOTTOM_BORDER self.RULES_BORDER = 50 + self.OUTER_X_BORDER self.BORDER_PATH = join(self.RESOURCE_DIR, "Border5.png") self.B = 29 self.MIN_ART_HEIGHT = 850 - self.B self.B_ART_WIDTH = self.WIDTH self.rarity_colors = { "M": "#D15003", "R": "#DFBD6C", "U": "#C8C8C8", "C": self.FC, "L": self.FC, "T": self.FC, } self.la = AA(MA(SA("language.right"), SA("number.right")), NA(3)) self.lmiddle = AA( NA(self.WIDTH / 2), DivA(AA(SA("artist_brush.width"), NA(3), SA("artist.width")), NA(2), negative=True)) self.BOTTOM_BASE_INFO = NA(self.HEIGHT - 45) self.TOP_BASE_INFO = AA(SA("set.cap"), NA(-3)) self.pdf = Image(filename=join(self.RESOURCE_DIR, "PrintPdf.png")) self.text_to_use = "text" self.PDF_SAVE_LOCATION = join("test_images", "pdfs", deckName) if not os.path.exists(self.PDF_SAVE_LOCATION): os.makedirs(self.PDF_SAVE_LOCATION)
def layers(self, card): art_layers = { "bg": ColorBackgroundLayer("bg", content=Color(self.SHADOW_COLOR)), "art": FillIL("art", order=-5, XP50=NA(self.WIDTH / 2), top=NA(self.B + self.TOP_OUTER_BORDER), width=NA(self.B_ART_WIDTH), height=NA(self.MIN_ART_HEIGHT)), "border": ImageLayer("border", content=self.BORDER_PATH, left=NA(0), top=NA(0)) } layers = { "dot": PTL("dot", self.RELAY, 25, self.FC, content=".", left=AA(SA("set.right"), NA(self.SET_DOT_LANG_WIDTH)), ycenter=SA("set.ycenter")), "language": PTL("language", self.RELAY, self.INFO_SIZE, self.FC, content="EN", left=AA(SA("dot.right"), NA(self.SET_DOT_LANG_WIDTH)), base=self.BOTTOM_BASE_INFO), "artist_brush": ResizeIL("artist_brush", content=join(self.RESOURCE_DIR, "artist_brush_white.png"), width=NA(20), left=self.lmiddle, height=SA("set.height"), bottom=self.BOTTOM_BASE_INFO), "copyright": PTL("copyright", self.MPLANTIN, self.INFO_SIZE - 5, self.FC, right=NA(self.WIDTH - self.BORDER), bottom=self.BOTTOM_BASE_INFO), "name": PTL("name", self.BELEREN, self.NAME_SIZE, self.FC, left=NA(self.BORDER), base=NA(70 + self.TOP_OUTER_BORDER)), "flavor_name": PTL("flavor_name", self.MPLANTIN_ITAL, self.FLAVOR_NAME_SIZE, self.FC, left=SA("name.left"), base=AA(SA("name.base"), NA(self.FLAVOR_NAME_SIZE + 4))), "PT": PTL("PT", self.BELEREN, self.PT_LOYAL_SIZE, self.FC, right=NA(self.WIDTH - self.BORDER), base=self.BOTTOM_BASE_INFO), "loyalty": PTL("loyalty", self.BELEREN, self.PT_LOYAL_SIZE, self.FC, right=NA(self.WIDTH - self.BORDER), base=self.BOTTOM_BASE_INFO), "set": PTL("set", self.RELAY, self.INFO_SIZE, self.FC, left=NA(self.BORDER), base=self.BOTTOM_BASE_INFO), "number": PTL("number", self.RELAY, self.INFO_SIZE, self.FC, left=NA(self.BORDER), base=self.TOP_BASE_INFO), "rarity": PTL("rarity", self.RELAY, self.INFO_SIZE, self.FC, left=SA("artist_brush.left"), base=self.TOP_BASE_INFO), "artist": PTL("artist", self.BELEREN_SC, self.INFO_SIZE, self.FC, left=AA(SA("artist_brush.right"), NA(3)), base=self.BOTTOM_BASE_INFO), "mana_cost": ManaCost("mana_cost", font=self.BELEREN, font_size=self.NAME_SIZE, font_color=self.FC, right=NA(self.WIDTH - self.BORDER), bottom=AA(SA("name.base"), NA(4))), } standard_rules = { "type": PTL("type", self.BELEREN, self.TYPE_SIZE, self.FC, left=NA(self.BORDER), base=AA(SA("rules.top"), NA(-10))), "rules": RulesText("rules", self.MPLANTIN, self.MPLANTIN_ITAL, self.RULES_TEXT_SIZE, self.FC, self.RULES_TEXT_SIZE - 4, left=NA(self.RULES_BORDER), right=NA(self.WIDTH - self.RULES_BORDER), base=AA(SA("rarity.cap"), NA(-6))) } split_text_layers = { "split_name": PTL("split_name", self.BELEREN, self.NAME_SIZE, self.FC, left=SA("name.left"), base=NA(self.SPLIT_CENTER + self.NAME_SIZE)), "split_mana_cost": ManaCost("split_mana_cost", font=self.BELEREN, font_size=self.NAME_SIZE, font_color=self.FC, right=SA("mana_cost.right"), bottom=AA(SA("split_name.base"), NA(4))), "split_type": PTL("split_type", self.BELEREN, self.TYPE_SIZE, self.FC, left=SA("type.left"), base=AA(SA("split_rules.top"), NA(-10))), "split_rules": RulesText("split_rules", self.MPLANTIN, self.MPLANTIN_ITAL, self.RULES_TEXT_SIZE, self.FC, self.RULES_TEXT_SIZE - 4, left=SA("rules.left"), right=SA("rules.right"), base=AA(SA("split_name.cap"), NA(-6))) } split_kwargs = { "left": NA(0), "order": -5, "width": NA(self.B_ART_WIDTH), "height": NA(self.SPLIT_HEIGHT) } top_split_kwargs = { **split_kwargs, "YP50": NA((self.B + self.TOP_OUTER_BORDER + self.SPLIT_CENTER) / 2) } bottom_split_kwargs = { **split_kwargs, "YP50": NA((self.SPLIT_CENTER + self.SPLIT_END - 2) / 2) } split_art_layers = { "split_divider_top": GradL("split_divider_top", start="RGBA(0,0,0,0.0)", end=self.SHADOW_COLOR, left=NA(0), width=NA(self.WIDTH), bottom=NA(self.SPLIT_CENTER), height=NA(self.SPLIT_SHADOW_SIZE)), "split_divider_bottom": GradL("split_divider_bottom", start=self.SHADOW_COLOR, end="RGBA(0,0,0,0.0)", left=NA(0), width=NA(self.WIDTH), top=NA(self.SPLIT_CENTER - 1), height=NA(self.SPLIT_SHADOW_SIZE)), "split_art_top": Mask("split_art_top_mask", FillIL("split_art_top", **top_split_kwargs), **top_split_kwargs), "split_art_bottom": Mask("split_art_bottom_mask", FillIL("split_art_bottom", **bottom_split_kwargs), **bottom_split_kwargs) } adventure_rules = { "rules_box": Template( "rules_box", *[ RulesText("rules", self.MPLANTIN, self.MPLANTIN_ITAL, self.RULES_TEXT_SIZE, self.FC, self.RULES_TEXT_SIZE - 4, left=AA(SA("parent.xcenter"), NA(5)), right=AA(SA("parent.right"), NA(self.RULES_BORDER, negative=True)), ycenter=SA("template.ycenter")), Template("adventure_box", *[ RulesText("adventure_rules", self.MPLANTIN, self.MPLANTIN_ITAL, self.RULES_TEXT_SIZE, self.FC, self.RULES_TEXT_SIZE - 4, left=NA(0), right=AA(SA("parent.width"), NA(-5)), top=AA(SA("adventure_type.base"), NA(6))), PTL("adventure_type", self.MPLANTIN, self.RULES_TEXT_SIZE + 3, self.FC, left=SA("adventure_name.left"), cap=AA(SA("adventure_name.base"), NA(6))), PTL("adventure_name", self.MPLANTIN, self.RULES_TEXT_SIZE + 5, self.FC, left=NA(0), cap=NA(3)), ManaCost("adventure_mana_cost", font=self.BELEREN, font_size=self.RULES_TEXT_SIZE, font_color=self.FC, right=SA("adventure_rules.right"), top=NA(0), mana_size=self.RULES_TEXT_SIZE), ], left=NA(self.RULES_BORDER), right=AA(SA("rules.left"), NA(-10)), ycenter=SA("template.ycenter"), height=SA("null.height")), ], left=NA(0), width=NA(self.WIDTH), base=AA( SA("self.height"), SA("rarity.cap"), NA(-6), MA(SA("rules.bottom"), SA("adventure_box.bottom"), negative=True)), height=SA("template.height")), "type": PTL("type", self.BELEREN, self.TYPE_SIZE, self.FC, left=NA(self.BORDER), base=AA(SA("rules_box.top"), MinA(SA("adventure_box.top"), SA("rules.top")), NA(-10))), } if card['layout'] == 'adventure': layers = {**layers, **adventure_rules} elif card["layout"] == "split": layers = {**layers, **standard_rules, **split_text_layers} art_layers = {**art_layers, **split_art_layers} else: layers = {**layers, **standard_rules} return list(art_layers.values()), list(layers.values())
env["FLAVOR_SPLIT_OFFSET"] = 40 env["MIN_ART_HEIGHT"] = 850 - env["B"] env["B_ART_WIDTH"] = env["WIDTH"] env["OUTER_X_BORDER"] = (env["WIDTH"] - env["INNER_WIDTH"]) / 2 env["TOTAL_Y_BORDER"] = (env["HEIGHT"] - env["INNER_HEIGHT"]) env["BORDER"] = env["STANDARD_BORDER"] + env["OUTER_X_BORDER"] env["TOP_BORDER"] = env["STANDARD_BORDER"] + env["TOP_OUTER_BORDER"] env["BOTTOM_BORDER"] = env["STANDARD_BORDER"] + env["OUTER_Y_BOTTOM_BORDER"] env["RULES_BORDER"] = 50 + env["OUTER_X_BORDER"] env["BORDER_PATH"] = join(env["RESOURCE_DIR"], "Border5.png") return env[key] la = AA(MA(SA("language.right"), SA("number.right")), NA(3)) lmiddle = AA( NA(env("WIDTH") / 2), DivA(AA(SA("artist_brush.width"), NA(3), SA("artist.width")), NA(2), negative=True)) BOTTOM_BASE_INFO = NA(env("HEIGHT") - 45) TOP_BASE_INFO = AA(SA("set.cap"), NA(-3)) art_layers = { "bg": ColorBackgroundLayer("bg", content=Color("#181510")), "art": FillIL("art", order=-5,
def test_can_make_template_layer(self): l = PointTextLayer("layer", "Arial", 12, "Black", content="hello world", left=NA(30), top=NA(45)) temp = Template("temp", l, left=NA(0), width=NA(50), top=NA(0), height=NA(50))