def label_keys(self, image, label_type):
        """Label keys on image.

        Args:
            image (Image): PillowImage of image.
            label_type (str): Key of label type.
        """
        draw = ImageDraw.Draw(image)
        textbox_drawer = TextBoxDrawer(image, draw)
        labels = KEY_LABELS[label_type]
        for index, (vertices, width, height) in enumerate(KEY_AREAS):
            position = index % 7
            box = TextBox(
                vertices,
                width,
                height,
                color=LABEL_COLOURS[position],
                font_path="static/fonts/PatrickHand-Regular.ttf",
                font_size=120,
            )
            textbox_drawer.write_text_box(
                box,
                labels[position],
                horiz_just="center",
            )
    def data(self):
        """Create data for a copy of the Left and Right Cards resource.

        Returns:
            A dictionary of the one page for the resource.
        """
        image_path = "static/img/resources/left-right-cards/left-right-cards.png"
        image = Image.open(image_path)
        draw = ImageDraw.Draw(image)
        textbox_drawer = TextBoxDrawer(image, draw)
        for label, label_data in LABEL_DATA.items():
            label_text = label_data["text"]
            for (top_left, width, height) in label_data["areas"]:
                vertices = calculate_box_vertices(top_left, width, height)
                box = TextBox(vertices,
                              width,
                              height,
                              font_path=FONT_PATH,
                              font_size=FONT_SIZE,
                              angle=label_data["rotation"])
                textbox_drawer.write_text_box(
                    box,
                    label_text,
                    horiz_just="center",
                )
        image = image.rotate(90, expand=True)
        return {"type": "image", "data": image}
    def add_destination_box(self, page, direction, destination_name):
        """Add destination boxes to page.

        Args:
            page (Image): Page to add image to.
            direction (str): Direction boat is travelling.
            destination_name (str): Name of destination island.
        """
        draw = ImageDraw.Draw(page)
        textbox_drawer = TextBoxDrawer(page, draw)
        if direction == "left":
            x_position = 0
        else:
            x_position = BOX_WIDTH
        vertices = calculate_box_vertices(
            (x_position, BOX_HEIGHT * 3),
            BOX_WIDTH,
            BOX_HEIGHT,
        )
        text_box = TextBox(
            vertices,
            BOX_WIDTH,
            BOX_HEIGHT,
            font_path=FONT_PATH,
            font_size=50,
            color=FONT_COLOUR,
        )
        textbox_drawer.write_text_box(
            text_box,
            destination_name,
            horiz_just="center",
            vert_just="center",
        )
 def test_write_text_box_object_justification_smoke_test(self):
     image = Image.new("RGB", (1000, 1000))
     draw = ImageDraw.Draw(image)
     vertices = [(0, 0), (200, 0), (200, 100), (0, 100)]
     width = 200
     height = 100
     box = TextBox(vertices, width, height)
     for horiz_just in ["left", "center", "right"]:
         for vert_just in ["top", "center", "bottom"]:
             TextBoxDrawer.write_text_box_object(
                 image,
                 draw,
                 box,
                 "This is a string",
                 horiz_just=horiz_just,
                 vert_just=vert_just,
             )
     with translation.override("he"):
         for horiz_just in ["left", "center", "right"]:
             for vert_just in ["top", "center", "bottom"]:
                 TextBoxDrawer.write_text_box_object(
                     image,
                     draw,
                     box,
                     "עברית‬",
                     horiz_just=horiz_just,
                     vert_just=vert_just,
                 )
    def add_island_box(self, page, island_id, island_data):
        """Add island label to top of page.

        Args:
            page (Image): Page to add image to.
            island_id (str): ID of island.
            island_data (dict): Data of island.
        """
        draw = ImageDraw.Draw(page)
        textbox_drawer = TextBoxDrawer(page, draw)
        island_image = Image.open(BASE_PATH.format(island_id))
        island_width, island_height = island_image.size
        coords = (int(BOX_WIDTH - (island_width / 2)),
                  int(((BOX_HEIGHT * 2 * 0.7) - island_height) / 2))
        page.paste(island_image, box=coords)
        island_name_width = BOX_WIDTH * 2
        island_name_height = BOX_HEIGHT * 2 * 0.3
        vertices = calculate_box_vertices(
            (0, BOX_HEIGHT * 2 * 0.7), island_name_width, island_name_height)
        box = TextBox(
            vertices,
            island_name_width,
            island_name_height,
            font_path=FONT_PATH,
            font_size=200,
            color=FONT_COLOUR,
        )
        textbox_drawer.write_text_box(
            box,
            island_data["name"],
            horiz_just="center",
            vert_just="top",
        )
    def create_map_page(self):
        """Create map page for students.

        Returns:
            A dictionary of the data for the page.
        """
        path = BASE_PATH.format(MAP_TYPE)
        image = Image.open(path)
        draw = ImageDraw.Draw(image)
        textbox_drawer = TextBoxDrawer(image, draw)

        for island_id, island_data in ISLANDS.items():
            box_data = island_data["map-location"]
            top_left_coords = box_data["top-left-coords"]
            width = box_data["width"]
            height = box_data["height"]
            vertices = calculate_box_vertices(top_left_coords, width, height)
            box = TextBox(
                vertices,
                width,
                height,
                font_path=FONT_PATH,
                font_size=80,
                color=FONT_COLOUR,
            )
            textbox_drawer.write_text_box(
                box,
                island_data["name"],
                horiz_just="center",
                vert_just="top",
            )

        image = image.rotate(90, expand=True)
        page_data = {"type": "image", "data": image}
        return page_data
 def test_write_text_box_defaults_smoke_test(self):
     image = Image.new("RGB", (2000, 4000))
     draw = ImageDraw.Draw(image)
     tbd = TextBoxDrawer(image, draw)
     vertices = [(0, 0), (200, 0), (200, 100), (0, 100)]
     width = 200
     height = 100
     box = TextBox(vertices, width, height)
     tbd.write_text_box(
         box,
         "This is a string",
     )
 def test_write_text_box_object_rotated_smoke_test(self):
     image = Image.new("RGB", (1000, 1000))
     draw = ImageDraw.Draw(image)
     vertices = [(0, 200), (0, 0), (100, 0), (100, 200)]
     width = 200
     height = 100
     rotation = 90
     box = TextBox(vertices, width, height, angle=rotation)
     TextBoxDrawer.write_text_box_object(
         image,
         draw,
         box,
         "This is a string",
     )
 def test_write_text_box_object_params_smoke_test(self):
     image = Image.new("RGB", (1000, 1000))
     draw = ImageDraw.Draw(image)
     vertices = [(0, 0), (200, 0), (200, 100), (0, 100)]
     width = 200
     height = 100
     box = TextBox(vertices, width, height)
     TextBoxDrawer.write_text_box_object(
         image,
         draw,
         box,
         "This is a string",
         font_path="static/fonts/PatrickHand-Regular",
         font_size=17,
         line_spacing=10,
         color="#013291")
    def data(self):
        """Create data for a copy of the Job Badges resource.

        Returns:
            A dictionary of the one page for the resource.
        """
        image_path = "static/img/resources/job-badges/job-badges.png"
        image = Image.open(image_path)
        draw = ImageDraw.Draw(image)
        textbox_drawer = TextBoxDrawer(image, draw)

        # coordinates of top left point of text box
        top_left_x_coords = [50, 1200]
        top_left_y_coord = 100

        # Add text labels
        for label, label_text in LABEL_DATA.items():
            for top_left_x_coord in top_left_x_coords:
                vertices = calculate_box_vertices(
                    (top_left_x_coord, top_left_y_coord),
                    TEXTBOX_WIDTH,
                    TEXTBOX_HEIGHT
                )
                box = TextBox(
                    vertices=vertices,
                    width=TEXTBOX_WIDTH,
                    height=TEXTBOX_HEIGHT,
                    font_path=FONT_PATH,
                    font_size=FONT_SIZE,
                )
                textbox_drawer.write_text_box(
                    box,
                    label_text,
                    horiz_just="center",
                    vert_just="center",
                )

            # increase y coord for next name tag down
            top_left_y_coord += 675

        return {"type": "image", "data": image}
    def data(self):
        """Create data for a copy of the Number Hunt resource.

        Returns:
            A dictionary of the two pages for the resource.
        """
        pages = []

        prefilled_values = self.options["prefilled_values"].value
        number_order = self.options["number_order"].value

        image = Image.open(IMAGE_PATH.format("template"))
        draw = ImageDraw.Draw(image)
        textbox_drawer = TextBoxDrawer(image, draw)

        # Add text labels
        for label_id, label_data in LABEL_DATA.items():
            if label_id == "subtitle":
                label_text = self.subtitle_text()
            else:
                label_text = label_data["text"]
            top_left_coords = label_data["top-left-coords"]
            width = label_data["width"]
            height = label_data["height"]
            vertices = calculate_box_vertices(top_left_coords, width, height)
            box = TextBox(
                vertices,
                width,
                height,
                font_path=FONT_PATH,
                font_size=label_data["font-size"],
                color=label_data["font-colour"],
            )
            textbox_drawer.write_text_box(
                box,
                label_text,
                horiz_just=label_data["horiz-just"],
                vert_just=label_data["vert-just"],
            )

        # Add numbers to image (if required)
        if prefilled_values != "blank":
            range_min, range_max, font_size = self.get_number_range(
                prefilled_values)
            total_numbers = 31
            numbers = sample(range(range_min, range_max), total_numbers)
            if number_order == "sorted":
                numbers.sort()

            coord_x = 106
            base_coord_y = 161
            coord_y_increment = 107.8
            width = 264
            height = 88
            for i, number in enumerate(numbers):
                coord_y = base_coord_y + (coord_y_increment * i)
                vertices = calculate_box_vertices((coord_x, coord_y), width,
                                                  height)
                box = TextBox(
                    vertices,
                    width,
                    height,
                    font_path=FONT_PATH,
                    font_size=font_size,
                )
                textbox_drawer.write_text_box(
                    box,
                    str(number),
                    horiz_just="center",
                    vert_just="center",
                )
        pages.append({
            "type": "resource-number-hunt",
            "data": [image, INSTRUCTIONS_HTML],
            "thumbnail": True
        })
        return pages
    def add_boat_box(self, page, direction, island_name):
        """Add boat boxes to page.

        Args:
            page (Image): Page to add image to.
            direction (str): Direction boat is travelling.
            island_name (str): Name of island.
        """
        box = Image.new("RGB", (BOX_WIDTH, BOX_HEIGHT), "#fff")
        box_draw = ImageDraw.Draw(box)
        box_textbox_drawer = TextBoxDrawer(box, box_draw)

        # Add image
        boat_image = Image.open(BASE_PATH.format("boat"))
        boat_width, boat_height = boat_image.size
        # Boxes are 70% boat image, 10% island name, 20% boat name
        ratio = (BOX_HEIGHT * 0.7) / boat_height
        boat_image = boat_image.resize(
            (int(boat_width * ratio), int(boat_height * ratio)))
        if direction == "left":
            boat_image = boat_image.transpose(Image.FLIP_LEFT_RIGHT)
        boat_width, boat_height = boat_image.size

        box.paste(boat_image, box=(int((BOX_WIDTH / 2) - (boat_width / 2)), 0))
        # First Line Text
        text_width = BOX_WIDTH
        text_height = BOX_HEIGHT * 0.1
        vertices = calculate_box_vertices(
            (0, BOX_HEIGHT * 0.7),
            text_width,
            text_height,
        )
        text_box = TextBox(
            vertices,
            text_width,
            text_height,
            font_path=FONT_PATH,
            font_size=50,
            color=FONT_COLOUR,
        )
        box_textbox_drawer.write_text_box(
            text_box,
            island_name,
            horiz_just="center",
            vert_just="center",
        )
        # Second line of text
        text_width = BOX_WIDTH
        text_height = BOX_HEIGHT * 0.2
        vertices = calculate_box_vertices(
            (0, BOX_HEIGHT * 0.8),
            text_width,
            text_height,
        )
        text_box = TextBox(
            vertices,
            text_width,
            text_height,
            font_path=FONT_PATH,
            font_size=70,
            color=FONT_COLOUR,
        )
        if direction == "left":
            boat_text = _("Boat A")
            x_position = 0
        else:
            boat_text = _("Boat B")
            x_position = BOX_WIDTH
        box_textbox_drawer.write_text_box(
            text_box,
            boat_text,
            horiz_just="center",
            vert_just="center",
        )
        box = box.transpose(Image.ROTATE_180)
        page.paste(box, box=(x_position, BOX_HEIGHT * 2))