Выбрать главу

      self.end_headers()

      return f

Метод gettext() проверяет, что запрос, передаваемый нашему обработчику запросов в переменной пути - правильный URI, сверяя его с регулярным выражением. Функция match() из модуля Питона re возвращает MatchObject (объект сопоставления), если регулярное выражение соответствует параметру, и None, если нет. Если есть соответствие, мы возвращаем содержание первой группы объекта сопоставления (символы, которые соответствуют выражению между круглыми скобками в регулярном выражении, в нашем случае значение текстового аргумента), в противном случае мы возвращаем None:

   def gettext(self):

      match = re.match(r'^.*/captcha\?text=(.*)$',

                       self.path)

      if match != None:

         return match.group(1)

      return None

Теперь мы добрались до задачи, специфичной для Блендера - сгенерировать рендеренный в 3D текст, который будет возвращён в виде png изображения. Метод captcha() принимает текст для рендера как аргумент, и возвращает имя файла сгенерированного изображения. Мы допускаем, что освещение и камера в .blend файле, в котором мы запускаем captcha.py, настроены правильно, чтобы удобочитаемо отображать наш текст. Следовательно, метод captcha() просто настраивает правильным образом объект Text3d и рендерит его.

Первая задача состоит в том, чтобы определить текущую сцену и проверить, присутствует ли объект с именем Text, который можно использовать заново (выделено). Заметьте, что вполне допустимо иметь другие объекты на сцене, чтобы ещё более затемнить отображение:

   def captcha(self,text):

      import Blender

      scn = Blender.Scene.GetCurrent()

      text_ob = None

      for ob in scn.objects:

         if ob.name == 'Text' :

            text_ob = ob.getData()

            break

Если не нашлось никакого ранее используемого объекта Text3d, создаём новый :

      if text_ob == None:

         text_ob = Blender.Text3d.New('Text')

         ob=scn.objects.new(text_ob)

         ob.setName('Text')

Следующий шаг - установить текст объекта Text3d в значение аргумента, переданного в метод captcha(), и сделать его трёхмерным, настроив глубину выдавливания. Мы также изменяем ширину символов и сокращаем расстояние между ними, чтобы ухудшить разделение. Добавление небольшого скоса (bevel) смягчит контуры символов, что может добавить трудностей для робота, различающего символы, если настроено искусное освещение (выделено). Мы могли бы решить использовать другой шрифт для нашего текста, который ещё труднее для чтения ботом, и здесь как раз место для установки такого шрифта (смотри следующий информационный блок).

Чего-то не хватает

Документация API Блендера имеет небольшой пропуск: как будто не существует способа настроить другой шрифт для объекта Text3d. Тем не менее, есть недокументированный метод setFont(), который принимает объект Font в качестве аргумента. Код, выполняющий изменение шрифта должен выглядеть похожим на это:

fancyfont=Text3d.Load('/usr/share/fonts/ttf/myfont.ttf')

text_ob.setFont(fancyfont)

Тем не менее, мы решили не включать этот код, частично потому что он недокументирован, но по большей части потому, что доступные шрифты существенно отличаются от системы к системе. Если у Вас есть подходящий доступный шрифт, во что бы то ни стало используйте его. Скрипт, пишущий шрифтами, которые, например, напоминают почерк, могут поднять планку сложности для компьютера ещё выше .

Последним  шагом нужно обновить дисплейный список Блендера для этого объекта, чтобы наши изменения были отрендерены:

      text_ob.setText(text)

      text_ob.setExtrudeDepth(0.3)

      text_ob.setWidth(1.003)

      text_ob.setSpacing(0.8)

      text_ob.setExtrudeBevelDepth(0.01)

      ob.makeDisplayList()

Как только наш объект Text3d будет на месте, нашей следующей задачей станет отрендерить его изображение в файл. Сначала мы извлекаем контекст рендера из текущей сцены и устанавливаем displayMode в 0, чтобы предотвратить появление дополнительного окна рендера:

      context = scn.getRenderingContext()

      context.displayMode=0

Затем, мы устанавливаем размер изображения и указываем, что нам нужен формат png. Включением RGBA и установкой альфа-режима в 2 мы гарантируем, что там не будет видно никакого неба, и что наше изображение будет иметь хороший прозрачный фон: