Example #1
0
 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")
Example #2
0
 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]
Example #3
0
 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")
Example #4
0
 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")
Example #5
0
 def test_template_with_max_attribute_can_render(self):
     c1 = ColorLayer("color1",
                     content="Green",
                     left=NA(0),
                     width=NA(50),
                     top=NA(0),
                     height=NA(50))
     c2 = ColorLayer("color2",
                     content="Blue",
                     left=NA(0),
                     width=NA(60),
                     top=SA("color1.bottom"),
                     height=NA(50))
     text = PTL("test",
                "Arial",
                15,
                "Black",
                content="Hello World",
                left=MinA(SA("color1.right"), SA("color2.right")),
                top=SA("color2.bottom"))
     bg = ColorBackgroundLayer("name", content="White")
     layers = [c1, c2, bg, text]
     temp = Template("temp",
                     *layers,
                     left=NA(0),
                     top=NA(0),
                     width=NA(300),
                     height=NA(300))
     temp.update_bounds()
     assert text["left"] == 60
Example #6
0
    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")
Example #7
0
    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
Example #8
0
 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()
Example #9
0
    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()
Example #10
0
    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
Example #11
0
 def test_exception_raised_if_no_existant_layer_is_referenced_in_SA(self):
     with pytest.raises(LayerDoesNotExistError):
         pt = PTL("test",
                  "Arial",
                  15,
                  "Black",
                  content="Hello",
                  left=NA(0),
                  top=NA(0))
         sq = ColorLayer("square",
                         content="Red",
                         left=NA(0),
                         top=SA("doesnotexist.bottom"),
                         width=NA(20),
                         height=NA(20))
         bg = ColorBackgroundLayer("bg", content="Green")
         bg2 = ColorBackgroundLayer("bg2", content="White")
         temp2 = Template("temp2",
                          sq,
                          bg,
                          left=NA(0),
                          width=NA(25),
                          top=NA(0),
                          height=NA(25))
         temp = Template("temp",
                         pt,
                         bg2,
                         temp2,
                         left=NA(0),
                         width=NA(100),
                         top=NA(0),
                         height=NA(100))
         temp.update_bounds()
         # from pprint import pprint
         # pprint(temp.get_layer("temp2").__dict__)
         temp.render().save(
             filename=
             "tests/images/test_exception_raised_if_no_existant_layer_is_referenced_in_SA.png"
         )
Example #12
0
    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")
Example #13
0
        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")
Example #14
0
    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())
Example #15
0
    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,
           XP50=NA(env("WIDTH") / 2),
           top=NA(env("B") + env("TOP_OUTER_BORDER")),
           width=NA(env("B_ART_WIDTH")),
           height=NA(env("MIN_ART_HEIGHT"))),
    "border":
    ImageLayer("border", content=env("BORDER_PATH"), left=NA(0), top=NA(0))
}
layers = {
    "dot":
    PTL("dot",
        env("RELAY"),
        env("DOT_HEIGHT"),
Example #16
0
def main():
    RESOURCE_DIR = join(os.getcwd(), "resources")
    SETS = join(RESOURCE_DIR, "card_data", "sets.json")
    TEST_DIR = "test_images"

    MPLANTIN = join(RESOURCE_DIR, "fonts", "MPlantin.ttf")
    BELEREN_SC = join(RESOURCE_DIR, "fonts", "Beleren_small_caps.ttf")
    BELEREN = join(RESOURCE_DIR, "fonts", "Jace_Beleren_bold.ttf")
    MPLANTIN_BOLD = join(RESOURCE_DIR, "fonts", "MPlantin_bold.ttf")
    MPLANTIN_ITAL = join(RESOURCE_DIR, "fonts", "MPlantin_italic.ttf")
    RELAY = join(RESOURCE_DIR, "fonts", "Relay_medium.ttf")
    FC = "White"
    FLAVOR_SPLIT_COLOR = "RGBA(255, 255, 255, 0.6)"
    FLAVOR_SPLIT_OFFSET = 40

    if os.path.isfile(SETS):
        with open(SETS, "r") as f:
            sets = json.load(f)
    else:
        raise ValueError("sets.json not found.")

    myset = "WAR"
    # JSON = join(RESOURCE_DIR, "card_data", f"{myset}.json")
    # JSON = join(RESOURCE_DIR, "card_data", f"mardu_aristocrats_M20.json")
    # TOKENS = join(RESOURCE_DIR, "card_data", f"tokens.json")
    # ANGELS = join(RESOURCE_DIR, "card_data", f"mardu_angels_M20.json")
    JSON = join(RESOURCE_DIR, "set_data", f"{myset}.json")
    # SULTAI_FLASH = join(RESOURCE_DIR, "card_data", f"sultai_flash.json")

    SAVE_LOCATION = myset
    # SAVE_LOCATION = "sultai_flash"

    # JSON = SULTAI_FLASH
    # JSON = TOKENS
    """make directory in art"""
    # if not os.path.isdir(join(RESOURCE_DIR, "art", myset)): # dir does not exist
    #     os.mkdir(join(RESOURCE_DIR, "art", myset))
    """make directory in render dir"""
    if not os.path.isdir(join("test_images", "all_render",
                              SAVE_LOCATION)):  # dir does not exist
        os.mkdir(join("test_images", "all_render", SAVE_LOCATION))
    """load cards"""
    with open(JSON, "r") as f:
        cards = json.load(f)
    """load tokens"""
    # with open(TOKENS, "r") as f:
    #     tokens = json.load(f)

    BORDER = 45
    RULES_BORDER = 52
    HEIGHT = 1050
    WIDTH = 752
    SET_DOT_LANG_WIDTH = 5
    INFO_SIZE = 18
    # FONT_SIZE = 40
    NAME_SIZE = 38
    TYPE_SIZE = 33
    PT_LOYAL_SIZE = 40
    RULES_TEXT_SIZE = 25

    la = AA(MA(SA("language.right"), SA("number.right")), NA(3))
    lmiddle = AA(
        NA(WIDTH / 2),
        DivA(AA(SA("artist_brush.width"), NA(3), SA("artist.width")),
             NA(2),
             negative=True))

    art_layers = {
        "bg":
        ColorBackgroundLayer("bg", content=Color("Black")),
        "art":
        FillIL("art",
               order=-5,
               XP50=NA(WIDTH / 2),
               YP50=NA(HEIGHT / 2),
               width=NA(WIDTH),
               height=NA(HEIGHT)),
        "shadow1":
        ColorLayer("shadow1",
                   content="RGBA(0,0,0,0.4)",
                   left=NA(0),
                   width=NA(WIDTH),
                   top=NA(0),
                   bottom=SA("shadow2.top")),
        "shadow2":
        GradL("shadow2",
              start="RGBA(0,0,0,0.4)",
              end="RGBA(0,0,0,0.0)",
              left=NA(0),
              width=NA(WIDTH),
              top=SA("name.bottom"),
              height=NA(200)),
        "shadow3":
        GradL("shadow3",
              start="RGBA(0,0,0,0.0)",
              end="RGBA(0,0,0,0.7)",
              left=NA(0),
              width=NA(WIDTH),
              bottom=SA("shadow4.top"),
              top=AA(SA("type.cap"), NA(-150))),
        "shadow4":
        ColorLayer("shadow4",
                   content="RGBA(0,0,0,0.7)",
                   left=NA(0),
                   width=NA(WIDTH),
                   bottom=NA(HEIGHT + 1),
                   top=SA("rules.YP70"))
    }
    no_content_reset = {
        "dot":
        PTL("dot",
            RELAY,
            25,
            FC,
            content=".",
            left=AA(SA("set.right"), NA(SET_DOT_LANG_WIDTH)),
            ycenter=SA("set.ycenter")),
        "language":
        PTL("language",
            RELAY,
            INFO_SIZE,
            FC,
            content="EN",
            left=AA(SA("dot.right"), NA(SET_DOT_LANG_WIDTH)),
            base=NA(HEIGHT - BORDER)),
        "artist_brush":
        ResizeIL("artist_brush",
                 content=join(RESOURCE_DIR, "artist_brush_white.png"),
                 width=NA(20),
                 left=lmiddle,
                 height=SA("set.height"),
                 bottom=NA(HEIGHT - BORDER)),
        "copyright":
        PTL("copyright",
            MPLANTIN,
            INFO_SIZE - 5,
            FC,
            right=NA(WIDTH - BORDER),
            bottom=SA("set.bottom")),
    }
    layers = {
        "name":
        PTL("name", BELEREN, NAME_SIZE, FC, left=NA(BORDER), base=NA(80)),
        "type":
        PTL("type",
            BELEREN,
            TYPE_SIZE,
            FC,
            left=NA(BORDER),
            base=AA(SA("rules.top"), NA(-10))),
        "PT":
        PTL("PT",
            BELEREN,
            PT_LOYAL_SIZE,
            FC,
            right=NA(WIDTH - BORDER),
            base=SA("set.base")),
        "loyalty":
        PTL("loyalty",
            BELEREN,
            PT_LOYAL_SIZE,
            FC,
            right=NA(WIDTH - BORDER),
            base=SA("set.base")),
        "set":
        PTL("set",
            RELAY,
            INFO_SIZE,
            FC,
            left=NA(BORDER),
            base=NA(HEIGHT - BORDER)),
        "number":
        PTL("number",
            RELAY,
            INFO_SIZE,
            FC,
            left=NA(BORDER),
            base=AA(SA("set.cap"), NA(-3))),
        "rarity":
        PTL("rarity",
            RELAY,
            INFO_SIZE,
            FC,
            left=SA("artist_brush.left"),
            base=SA("number.base")),
        "artist":
        PTL("artist",
            BELEREN_SC,
            INFO_SIZE,
            FC,
            left=AA(SA("artist_brush.right"), NA(3)),
            base=SA("set.base")),
        "mana_cost":
        ManaCost("mana_cost",
                 font=BELEREN,
                 font_size=NAME_SIZE,
                 font_color=FC,
                 right=NA(WIDTH - BORDER),
                 bottom=AA(SA("name.base"), NA(4))),
        "rules":
        RulesText("rules",
                  MPLANTIN,
                  MPLANTIN_ITAL,
                  RULES_TEXT_SIZE,
                  FC,
                  RULES_TEXT_SIZE - 4,
                  left=NA(RULES_BORDER),
                  right=NA(WIDTH - RULES_BORDER),
                  bottom=AA(SA("PT.bottom"), NA(-PT_LOYAL_SIZE), NA(-5))),
        # "flavor_split": ColorLayer("flavor_split", left=NA(RULES_BORDER + FLAVOR_SPLIT_OFFSET),
        #     right=NA(WIDTH - RULES_BORDER - FLAVOR_SPLIT_OFFSET), height=NA(2),
        #     bottom=AA(SA("flavor.top"), NA(-5))),
        # "flavor": RulesText("flavor", MPLANTIN, MPLANTIN_ITAL, RULES_TEXT_SIZE, FC,
        #     RULES_TEXT_SIZE - 4, left=NA(RULES_BORDER), right=NA(WIDTH-RULES_BORDER),
        #     bottom=AA(SA("PT.bottom"), NA(-PT_LOYAL_SIZE), NA(-5))),
    }

    text_template = Template("text_temp",
                             *layers.values(),
                             *no_content_reset.values(),
                             left=NA(0),
                             width=NA(WIDTH),
                             top=NA(0),
                             height=NA(HEIGHT))
    art_template = Template("art_temp",
                            *art_layers.values(),
                            order=-5,
                            left=NA(0),
                            width=NA(WIDTH),
                            top=NA(0),
                            height=NA(HEIGHT))

    name = text_template.get_layer("name")

    with_art = list(os.listdir(join(RESOURCE_DIR, "art", myset)))
    cards = [c for c in cards if f"{c['name']}_{c['id']}.jpg" in with_art]
    cards = [c for c in cards if c['name'] == "Nicol Bolas, Dragon-God"]
    print(len(cards))

    # no_content_reset["copyright"].content = f"™ & © {datetime.now().year} Wizards of the Coast"
    # no_content_reset["copyright"].content = f"™ & © {datetime.now().year} WOTC"
    loga = math.ceil(math.log10(len(cards)))
    temp = Template("template",
                    text_template,
                    art_template,
                    left=NA(0),
                    width=NA(WIDTH),
                    top=NA(0),
                    height=NA(HEIGHT))
    temp.mana_image_format = "svg"
    temp.resource_dir = RESOURCE_DIR
    max_card_length = max(len(c['name']) for c in cards)
    row = f"| {{:0{loga}}}/{{:0{loga}}} | {{}} | {{}} | {{:07.3f}} |"
    total = 0

    for i, card in enumerate(sorted(cards, key=lambda x: x['name'])):
        start_time = time.time()
        for shadow in ["shadow3", "shadow4"]:
            l = temp.get_layer(shadow)
            l.pre_render = None

        reset_layers = list(layers) + ["art"]
        for name in reset_layers:
            layer = temp.get_layer(name)
            layer.unset_content_and_pre_render()
            # layer.content = None
            # layer.pre_render = None
            if layer.name in card:
                layer.content = card[layer.name]
        temp.get_layer("artist_brush").pre_shadow = None

        if "Creature" in card["types"]:
            layers["PT"].content = f"{card['power']}/{card['toughness']}"
        # print(card)
        # print(repr(temp.get_layer("name").content))
        count = 999
        sset = [s for s in sets if s['code'] == card['set']]
        if len(sset) == 1:
            count = sset[0]["count"]
        number = card['number'].upper().zfill(3)
        layers["number"].content = f"{number}/{count:03}"
        rarity_colors = {
            "M": "#D15003",
            "R": "#DFBD6C",
            "U": "#C8C8C8",
            "C": FC,
            "L": FC,
            "T": FC,
        }
        rarity = card["rarity"][0].upper()
        layers["rarity"].color = rarity_colors[rarity]
        layers["rarity"].content = rarity

        rules = ""
        text_to_use = "text"
        if card[text_to_use] is not None:
            rules = card[text_to_use]
        if card["flavor"] is not None:
            flavor = "\n".join(
                [f"<i>{f}</i>" for f in card['flavor'].split('\n')])
            if rules == "":
                rules = flavor
            else:
                rules += "\n" + flavor

        if rules != "":
            temp.get_layer("rules").content = rules
        art_path = join(RESOURCE_DIR, "art", card['set'], f"{card['name']}_{card['id']}.jpg") \
                .replace("//", "__")
        temp.get_layer("art").content = art_path if os.path.isfile(
            art_path) else None

        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()
        render_text.save(filename="test.png")
        image.composite(render_text, left=0, top=0)

        # xb = Bounds(start=BORDER - 10, end=WIDTH - BORDER + 10)
        # yb = Bounds(start=temp.get_layer("type")["top"] - 10,
        #     end=temp.get_layer("rules")['bottom'] + 10)
        # exp = render_bg.export_pixels(x=int(xb['start']), y=int(yb['start']),
        #     width=int(xb['full']), height=int(yb['full']))

        # with Image(width=int(xb['full']), height=int(yb['full']),
        #         background=Color("Transparent")) as blur_image:
        #     blur_image.import_pixels(width=int(xb['full']), height=int(yb['full']),
        #        channel_map="RGBA", storage="char", data=exp)
        #     with Image(width=blur_image.width, height=blur_image.height,
        #             background=Color("RGBA(0,0,0,0.2)")) as dark:
        #         blur_image.composite(dark, 0, 0)
        #     blur_image.blur(radius=10, sigma=5)
        #     with Image(width=blur_image.width, height=blur_image.height,
        #             background=Color("Black")) as mask:
        #         with Drawing() as ctx:
        #             ctx.fill_color = Color("White")
        #             ctx.rectangle(0, 0, width=mask.width,
        #                     height=mask.height, radius=15)
        #             ctx(mask)
        #         apply_mask(blur_image, mask)
        #     image.composite(blur_image, left=int(xb['start']), top=int(yb['start']))

        image.save(filename=join(
            "test_images", "all_render", f"{SAVE_LOCATION}",
            f"{card['name']}_{card['id']}.jpg").replace("//", "__"))
        # image.save(filename=join("test_images", "all_render", "Printing", f"{SAVE_LOCATION}", f"{card['name']}_{card['id']}.jpg").replace("//", "__"))
        # image.save(filename=join("test_images", "all_render", "Printing", f"{SAVE_LOCATION}", f"{card['name']}.jpg").replace("//", "__"))
        temp.unset_bounds_and_attributes()

        delta = time.time() - start_time
        total += delta
        if delta < .250:
            color = "green"
        elif delta < .500:
            color = "yellow"
        else:
            color = "red"
        print(f"\r{row}".format(
            i,
            len(cards) - 1,
            colored(f"{card['name']: <{max_card_length}}", color),
            colored(f"{delta:03.3f}", color), total))