crossword-8.x-1.x-dev/modules/crossword_image/src/Plugin/crossword/crossword_image/CrosswordThumbnailBase.php

modules/crossword_image/src/Plugin/crossword/crossword_image/CrosswordThumbnailBase.php
<?php

namespace Drupal\crossword_image\Plugin\crossword\crossword_image;

use Drupal\crossword_image\CrosswordImagePluginBase;
use Drupal\file\FileInterface;

/**
 * A base class for thumbnail images of crossword files.
 *
 * Simple extensions of this can set the image type, square size,
 * and line width. More advanced extensions can use the helper functions
 * provided on this class to add numerals and circles and fill.
 */
abstract class CrosswordThumbnailBase extends CrosswordImagePluginBase {

  /**
   * The width of a square in pixels.
   *
   * @var int
   */
  protected $squareSize;

  /**
   * The width of a line in pixels.
   *
   * @var int
   */
  protected $lineSize;

  /**
   * {@inheritdoc}
   */
  public function createImageResource(FileInterface $file) {
    $data = $this->crosswordDataService->getData($file);
    $grid = $data['puzzle']['grid'];
    $image = $this->buildGrid($grid);
    $this->addEmbeddedImages($grid, $image);
    return $image;
  }

  /**
   * Make a black grid on white background.
   *
   * The result of this function can be used by other helper functions
   * to add things like fill and numerals.
   *
   * @param array $grid
   *   The grid part of the crossword data array.
   *
   * @return resource
   *   The most basic crossword thumbnail.
   */
  public function buildGrid(array $grid) {
    $square_size = $this->squareSize;
    $line_size = $this->lineSize;
    $width = count($grid[0]) * $square_size + $line_size / 2;
    $height = count($grid) * $square_size + $line_size / 2;
    $image = @imagecreatetruecolor($width, $height);
    $white = imagecolorallocate($image, 255, 255, 255);
    foreach ($grid as $row_index => $row) {
      foreach ($row as $col_index => $square) {
        if ($square['fill'] !== NULL) {
          $color = $white;
          @imagefilledrectangle($image, $col_index * $square_size + $line_size / 2, $row_index * $square_size + $line_size / 2, ($col_index + 1) * $square_size - $line_size / 2, ($row_index + 1) * $square_size - $line_size / 2, $color);
        }
      }
    }
    return $image;
  }

  /**
   * Add circles to an existing image.
   *
   * @param array $grid
   *   The grid part of the crossword data array.
   * @param resource $image
   *   The crossword image we are adding to.
   *
   * @return resource
   *   The image with added circles.
   */
  public function addCircles(array $grid, $image) {
    $black = imagecolorallocate($image, 0, 0, 0);
    foreach ($grid as $row_index => $row) {
      foreach ($row as $col_index => $square) {
        if (!empty($square['circle'])) {
          $start = -180;
          $end = 180;
          $height = $width = $this->squareSize;
          $x = ($col_index + 0.5) * $this->squareSize;
          $y = ($row_index + 0.5) * $this->squareSize;
          // Draw two arcs to make the line thicker.
          @imagearc($image, $x, $y, $width, $height, $start, $end, $black);
          @imagearc($image, $x, $y, $width - 1, $height - 1, $start, $end, $black);
        }
      }
    }
    return $image;
  }

  /**
   * Add numerals to an existing image.
   *
   * @param array $grid
   *   The grid part of the crossword data array.
   * @param resource $image
   *   The crossword image we are adding to.
   *
   * @return resource
   *   The image with added numerals.
   */
  public function addNumerals(array $grid, $image) {
    $square_size = $this->squareSize;
    $line_size = $this->lineSize;
    $black = imagecolorallocate($image, 0, 0, 0);
    $font = $this->font ?? 3;
    foreach ($grid as $row_index => $row) {
      foreach ($row as $col_index => $square) {
        if (isset($square['numeral'])) {
          $color = $black;
          @imagestring($image, $font, $col_index * $square_size + $line_size / 2 + $line_size, $row_index * $square_size + $line_size / 2, $square['numeral'], $color);
        }
      }
    }
    return $image;
  }

  /**
   * Add fill to an existing image.
   *
   * @param array $grid
   *   The grid part of the crossword data array.
   * @param resource $image
   *   The crossword image we are adding to.
   * @param bool $only_hints
   *   TRUE if you only want to add the fill for squares marked as hint.
   *
   * @return resource
   *   The image with added fill.
   */
  public function addFill(array $grid, $image, $only_hints = FALSE) {
    $square_size = $this->squareSize;
    $black = imagecolorallocate($image, 0, 0, 0);
    $font = $this->extensionList->getPath('crossword_image') . '/fonts/RobotoMono-Regular.ttf';
    // The RobotoMono regular has approximately this aspect ratio.
    $font_aspect = 1.29;
    foreach ($grid as $row_index => $row) {
      foreach ($row as $col_index => $square) {
        if (isset($square['fill']) && (!$only_hints || isset($square['hint']))) {
          if (!empty($square['rebus'])) {
            $angle = -45;
            // Prescribe a total width for the rebus text.
            $text_width = $square_size / sqrt(2);
            $size = $text_width / strlen($square['fill']) * $font_aspect;
            // Bottom left of text. Kind of magic.
            $x = ($col_index + 0.15) * $square_size;
            $y = ($row_index + 0.41) * $square_size - sqrt($size) / 4;
          }
          else {
            $size = $this->squareSize / 2;
            $angle = 0;
            // Bottom left of text.
            $x = ($col_index + 0.5) * $square_size - $size / 2 / $font_aspect;
            $y = ($row_index + 1) * $square_size - $size / 2;
          }
          @imagettftext($image, $size, $angle, $x, $y, $black, $font, $square['fill']);
        }
      }
    }
    return $image;
  }

  /**
   * Add hints to an existing image.
   *
   * @param array $grid
   *   The grid part of the crossword data array.
   * @param resource $image
   *   The crossword image we are adding to.
   *
   * @return resource
   *   The image with added hints.
   */
  public function addHints(array $grid, $image) {
    return $this->addFill($grid, $image, TRUE);
  }

  /**
   * Embeds images into an existing image.
   *
   * @param array $grid
   *   The grid part of the crossword data array.
   * @param resource $image
   *   The crossword image we are adding to.
   *
   * @return resource
   *   The image with added embedded images.
   */
  public function addEmbeddedImages(array $grid, $image) {
    $square_size = $this->squareSize;
    $line_size = $this->lineSize;
    foreach ($grid as $row_index => $row) {
      foreach ($row as $col_index => $square) {
        if (isset($square['image'])) {
          $data = base64_decode($square['image']['data']);
          $embedded = imagecreatefromstring($data);
          if ($embedded === FALSE) {
            continue;
          }
          $width = $square['image']['width'] * $square_size - $line_size;
          $height = $square['image']['width'] * $square_size - $line_size;
          $embedded = @imagescale($embedded, $width, $height);
          @imagecopy(
            $image,
            $embedded,
            $col_index * $square_size + $line_size / 2,
            $row_index * $square_size + $line_size / 2,
            0,
            0,
            $width,
            $height
          );
          imagedestroy($embedded);
        }
      }
    }
    return $image;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc