textimage.module in Textimage 7.3
Same filename and directory in other branches
Textimage - Provides text to image manipulations.
File
textimage.moduleView source
<?php
/**
* @file
* Textimage - Provides text to image manipulations.
*/
/**
* Define constants.
*/
define('TEXTIMAGE_FONTYOURFACE_MIN_VERSION', '7.x-2.6');
define('TEXTIMAGE_MEDIA_MIN_VERSION', '7.x-1.2');
define('TEXTIMAGE_JQUERY_COLORPICKER_MIN_VERSION', '7.x-1.0-rc1');
define('TEXTIMAGE_TOKEN_MIN_VERSION', '7.x-1.5');
/**
* Hooks implementations.
*/
/**
* Implements hook_help().
*/
function textimage_help($path, $arg) {
switch ($path) {
case 'admin/config/media/textimage':
$output = '<p>';
$output .= t('Textimage provides image effects to generate images with overlaid text.') . ' ';
$output .= t('Use <a href="@image">Image styles</a> features to create Image styles.', array(
'@image' => url('admin/config/media/image-styles'),
)) . ' ';
$output .= t('Adding Textimage effects to a style will identify it as relevant for Textimage.') . ' ';
$output .= t('On the edit image style form, a "Textimage options" section allows selecting Textimage-specific options for the style.');
$output .= '</p>';
return $output;
}
}
/**
* Implements hook_theme().
*/
function textimage_theme() {
$theme = array(
// Get a textimage from a stored image style.
'textimage_style_image' => array(
'variables' => array(
'style_name' => '',
'text' => array(),
'format' => 'png',
'alt' => 'Image not available.',
'title' => '',
'attributes' => array(),
'caching' => TRUE,
'node' => NULL,
'source_image_file' => NULL,
),
),
// Get a textimage from a programmatically created image style.
'textimage_direct_image' => array(
'variables' => array(
'effects' => array(),
'text' => array(),
'format' => 'png',
'alt' => 'Image not available.',
'title' => '',
'attributes' => array(),
'caching' => TRUE,
),
),
// Format a textimage.
'textimage_formatter' => array(
'variables' => array(
'textimage' => NULL,
'style_name' => '',
'effects' => array(),
'text' => array(),
'format' => 'png',
'caching' => TRUE,
'node' => NULL,
'source_image_file' => NULL,
'target_uri' => NULL,
'force_hashed_filename' => FALSE,
'alt' => '',
'title' => '',
'attributes' => array(),
'image_container_attributes' => array(),
'href' => '',
),
),
// Textimage background image effect - summary.
'textimage_background_effect_summary' => array(
'variables' => array(
'data' => NULL,
),
),
// Textimage text image effect - summary.
'textimage_text_effect_summary' => array(
'variables' => array(
'data' => NULL,
),
),
// Textimage GIF transparency effect - summary.
'textimage_gif_transparency_effect_summary' => array(
'variables' => array(
'data' => NULL,
),
),
// Render a string with color formatting.
'textimage_colored_string' => array(
'variables' => array(
'text' => '',
'foreground_color' => '#000000',
'background_color' => '',
'border' => FALSE,
'border_color' => '#000000',
),
),
);
return $theme;
}
/**
* Implements hook_menu().
*/
function textimage_menu() {
$items = array();
$items['admin/config/media/textimage'] = array(
'title' => 'Textimage',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'textimage_form_settings',
),
'access arguments' => array(
'administer image styles',
),
'description' => 'Configure Textimage settings.',
'weight' => 10,
'type' => MENU_NORMAL_ITEM,
'file' => 'textimage.admin.inc',
);
$items['admin/config/media/textimage/cleanup'] = array(
'title' => 'Cleanup Textimage',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'textimage_flush_all_form',
),
'access arguments' => array(
'administer image styles',
),
'description' => 'Cleanup Textimage stored images.',
'type' => MENU_CALLBACK,
'file' => 'textimage.admin.inc',
);
// Generate image derivatives of publicly available files, via
// URL request path. For local default filesystem only.
$stream_wrapper = file_stream_wrapper_get_instance_by_scheme(variable_get('file_default_scheme', 'public'));
if ($stream_wrapper instanceof DrupalLocalStreamWrapper) {
$directory_path = $stream_wrapper
->getDirectoryPath();
$items[$directory_path . '/textimage'] = array(
'title' => 'URL textimage generation',
'page callback' => 'textimage_url_deliver',
'access arguments' => array(
'generate textimage url derivatives',
),
'type' => MENU_CALLBACK,
);
}
return $items;
}
/**
* Implements hook_permission().
*/
function textimage_permission() {
return array(
'generate textimage url derivatives' => array(
'title' => t('Generate Textimage URL derivatives'),
'description' => t('Allows users to generate Textimage derivatives directly from an URL request.'),
),
);
}
/**
* Implements hook_file_download().
*
* Control the access to files underneath the styles directory.
*/
function textimage_file_download($uri) {
$path = file_uri_target($uri);
// Private file access for image style derivatives.
if (strpos($path, 'textimage') === 0) {
$args = explode('/', $path);
// Discard the first part of the path (textimage).
array_shift($args);
// Discard the style name.
array_shift($args);
// Remove the filename from the path.
array_shift($args);
// Then the remaining parts are the path to the image.
$original_uri = file_uri_scheme($uri) . '://' . implode('/', $args);
// Check that the file exists and is an image.
if ($info = image_get_info($uri)) {
// Check the permissions of the original to grant access to this image.
$headers = module_invoke_all('file_download', $original_uri);
if (!in_array(-1, $headers)) {
return array(
// Send headers describing the image's size, and MIME-type...
'Content-Type' => $info['mime_type'],
'Content-Length' => $info['file_size'],
);
}
}
return -1;
}
// Private file access for the original files. Note that we only
// check access for non-temporary images, since file.module will
// grant access for all temporary files.
$files = file_load_multiple(array(), array(
'uri' => $uri,
));
if (count($files)) {
$file = reset($files);
if ($file->status) {
return file_file_download($uri, 'image');
}
}
}
/**
* Implements hook_flush_caches().
*/
function textimage_flush_caches() {
return array(
'cache_textimage',
);
}
/**
* Implements hook_cron().
*/
function textimage_cron() {
// Remove temporary, uncached, image files.
if (file_exists(_textimage_get_store_path('uncached'))) {
if (file_unmanaged_delete_recursive(_textimage_get_store_path('uncached'))) {
_textimage_diag(t("Textimage temporary image files removed."), WATCHDOG_NOTICE);
}
else {
_textimage_diag(t("Textimage could not remove temporary image files."), WATCHDOG_ERROR, __FUNCTION__);
}
}
}
/**
* Implements hook_schema_alter().
*/
function textimage_schema_alter(&$schema) {
// Alter the schema adding fields required by Textimage.
require_once 'textimage.install';
$table_fields = _textimage_define_table_fields();
foreach ($table_fields as $table_name => $fields) {
foreach ($fields as $field_name => $field) {
$schema[$table_name]['fields'][$field_name] = $field;
}
}
}
/**
* Implements hook_token_info().
*/
function textimage_token_info() {
$type = array(
'name' => t('Textimage'),
'description' => t('Tokens related to Textimage'),
'needs-data' => 'node',
);
$tokens = array(
'uri' => array(
'name' => t("URI"),
'description' => t("The URI(s) of a Textimage generated for a node's field. Use like <strong>[textimage:uri:field{:display}{:sequence}]</strong>, where:<br/><strong>field</strong> is the machine name of the field for which the Textimage is generated (e.g. body or field_xxxx);<br/><strong>display</strong> is an optional indication of the display view mode (e.g. default, full, teaser, etc.); 'default' is used if not specified; <br/><strong>sequence</strong> is an optional indication of the URI to return if Textimage produces more images for the same field (like e.g. in a multi-value Image field); if not specified, a comma-delimited string of all the URIs generated will be returned."),
'dynamic' => TRUE,
),
'url' => array(
'name' => t("URL"),
'description' => t("The URL(s) of a Textimage generated for a node's field. Use like <strong>[textimage:url:field{:display}{:sequence}]</strong>, where:<br/><strong>field</strong> is the machine name of the field for which the Textimage is generated (e.g. body or field_xxxx);<br/><strong>display</strong> is an optional indication of the display view mode (e.g. default, full, teaser, etc.); 'default' is used if not specified; <br/><strong>sequence</strong> is an optional indication of the URL to return if Textimage produces more images for the same field (like e.g. in a multi-value Image field); if not specified, a comma-delimited string of all the URLs generated will be returned."),
'dynamic' => TRUE,
),
);
return array(
'types' => array(
'textimage' => $type,
),
'tokens' => array(
'textimage' => $tokens,
),
);
}
/**
* Implements hook_tokens().
*/
function textimage_tokens($type, $tokens, array $data = array(), array $options = array()) {
// Jumps out if not processing textimage tokens.
if ($type != 'textimage') {
return array();
}
// Jumps out with a warning if node is not available.
if (!isset($data['node'])) {
_textimage_diag(t('Textimage token(s) @tokens_list could not be resolved as no information about the context was available.', array(
'@tokens_list' => implode(', ', $tokens),
)), WATCHDOG_WARNING);
return array();
}
// Process tokens.
$replacements = TextimageImager::processTokens('url', $tokens, $data['node']);
$replacements += TextimageImager::processTokens('uri', $tokens, $data['node']);
return $replacements;
}
/**
* Implements hook_metatag_token_types_alter().
*
* Integration of Textimage tokens with the Metatag module.
*/
function textimage_metatag_token_types_alter(&$options) {
// Add Textimage tokens to the token types managed by Metatag,
// for the node context.
if ($options['context'] == 'node') {
if (!isset($options['token types'])) {
$options['token types'] = array();
}
if (!in_array('textimage', $options['token types'])) {
$options['token types'][] = 'textimage';
}
}
}
// There is not a way to specify a file in hook_image_effect_info.
// Effects .inc files are included here for the time being.
require_once 'effects/textimage_background.inc';
require_once 'effects/textimage_text.inc';
require_once 'effects/textimage_gif_transparency.inc';
/**
* Implements hook_image_styles_alter().
*/
function textimage_image_styles_alter(&$styles) {
// Adds textimage properties to the image styles when loading them.
foreach ($styles as &$style) {
TextimageStyles::isTextimage($style);
}
}
/**
* Implements hook_image_effect_info().
*/
function textimage_image_effect_info() {
$effects = array();
$effects['textimage_background'] = array(
'label' => t('Textimage background'),
'help' => t('Define size and background color of the Textimage, or a background image.'),
'effect callback' => 'textimage_background_effect',
'dimensions callback' => 'textimage_background_effect_dimensions',
'form callback' => 'textimage_background_effect_form',
'summary theme' => 'textimage_background_effect_summary',
);
$effects['textimage_text'] = array(
'label' => t('Textimage text'),
'help' => t('Define text font, size and positioning.'),
'effect callback' => 'textimage_text_effect',
'dimensions callback' => 'textimage_text_effect_dimensions',
'form callback' => 'textimage_text_effect_form',
'summary theme' => 'textimage_text_effect_summary',
);
$effects['textimage_gif_transparency'] = array(
'label' => t('Textimage GIF transparency'),
'help' => t('Define a color to set GIF transparency.'),
'effect callback' => 'textimage_gif_transparency_effect',
'dimensions passthrough' => TRUE,
'form callback' => 'textimage_gif_transparency_effect_form',
'summary theme' => 'textimage_gif_transparency_effect_summary',
);
return $effects;
}
/**
* Implements hook_image_style_flush().
*/
function textimage_image_style_flush($style) {
// Manage the textimage part of style flushing.
if (TextimageStyles::isTextimage($style)) {
TextimageStyles::flush($style);
}
}
/**
* Implements hook_image_style_save().
*/
function textimage_image_style_save($style) {
if (TextimageStyles::isTextimage($style)) {
TextimageStyles::save($style);
}
}
/**
* Implements hook_image_style_delete().
*/
function textimage_image_style_delete($style) {
if (TextimageStyles::isTextimage($style)) {
TextimageStyles::delete($style);
}
}
/**
* Implements hook_form_FORM_ID_alter().
*
* @see _textimage_image_style_form_form_alter()
*/
function textimage_form_image_style_form_alter(&$form, &$form_state, $form_id) {
require_once 'textimage.admin.inc';
_textimage_image_style_form_form_alter($form, $form_state, $form_id);
}
/**
* Implements hook_field_formatter_info().
*/
function textimage_field_formatter_info() {
$formatters = array(
'textimage' => array(
'label' => t('Textimage'),
'description' => t('Textimage formatter'),
'field types' => array(
'image',
'text',
'text_with_summary',
'text_long',
),
'settings' => array(
'image_style' => '',
'image_text_values' => 'merge',
'image_link' => '',
'image_alt' => '',
'image_title' => '',
),
),
);
return $formatters;
}
/**
* Implements hook_field_formatter_settings_form().
*/
function textimage_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
$display = $instance['display'][$view_mode];
$settings = $display['settings'];
// Image style setting.
$image_styles = TextimageStyles::getOptions(FALSE);
$element['image_style'] = array(
'#title' => t('Image style'),
'#type' => 'select',
'#default_value' => $settings['image_style'],
'#options' => $image_styles,
'#required' => TRUE,
'#description' => t('Only Textimage relevant image styles can be selected.'),
);
// Multi-value text field image generation settings.
if ($field['module'] == 'text' && $field['cardinality'] != 1) {
$options = array(
'merge' => t("Build one single image, styling together text values."),
'itemize' => t("Build multiple images, styling each text value in a separate image."),
);
$element['image_text_values'] = array(
'#title' => t('Multiple values text field'),
'#type' => 'radios',
'#default_value' => $settings['image_text_values'],
'#options' => $options,
'#required' => TRUE,
'#description' => t("Text values are styled following the sequence of 'Textimage text' effects in the image style."),
);
}
// Link setting.
$link_types = array(
'content' => t('Content'),
'file' => t('File'),
);
$element['image_link'] = array(
'#title' => t('Link image to'),
'#type' => 'select',
'#default_value' => $settings['image_link'],
'#empty_option' => t('Nothing'),
'#options' => $link_types,
);
// Image alt and title attribute settings.
$element['image_alt'] = array(
'#title' => t('Alternate text'),
'#type' => 'textfield',
'#default_value' => $settings['image_alt'],
'#description' => t('This text will be used by screen readers, search engines, or when the image cannot be loaded.') . ' ' . t('Tokens can be used.'),
'#maxlength' => 512,
);
$element['image_title'] = array(
'#type' => 'textfield',
'#title' => t('Title'),
'#default_value' => $settings['image_title'],
'#description' => t('The title is used as a tool tip when the user hovers the mouse over the image.') . ' ' . t('Tokens can be used.'),
'#maxlength' => 1024,
);
return $element;
}
/**
* Implements hook_field_formatter_settings_summary().
*/
function textimage_field_formatter_settings_summary($field, $instance, $view_mode) {
$display = $instance['display'][$view_mode];
$settings = $display['settings'];
$summary = array();
$image_styles = TextimageStyles::getOptions(FALSE);
// Unset possible 'No defined styles' option.
unset($image_styles['']);
// Styles could be lost because of enabled/disabled modules that defines
// their styles in code.
if (isset($image_styles[$settings['image_style']])) {
$summary[] = t('Image style: @style', array(
'@style' => $image_styles[$settings['image_style']],
));
}
else {
$summary[] = t('Image style: undefined');
}
// Multi-value text field image generation settings.
if ($field['module'] == 'text' && $field['cardinality'] != 1) {
$options = array(
'merge' => t("Build one image"),
'itemize' => t("Build multiple images"),
);
$summary[] = t('Multiple text values:') . ' ' . $options[$settings['image_text_values']];
}
// Display link setting only if image is linked.
$link_types = array(
'content' => t('Linked to content'),
'file' => t('Linked to file'),
);
if (isset($link_types[$settings['image_link']])) {
$summary[] = $link_types[$settings['image_link']];
}
// Display this setting only if alt text is specified.
if (!empty($settings['image_alt'])) {
$summary[] = t('Alternate text: @image_alt', array(
'@image_alt' => $settings['image_alt'],
));
}
// Display this setting only if title is specified.
if (!empty($settings['image_title'])) {
$summary[] = t('Title: @image_title', array(
'@image_title' => $settings['image_title'],
));
}
return implode('<br />', $summary);
}
/**
* Implements hook_field_formatter_view().
*/
function textimage_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
// If formatting a node, store entity for passing to theme.
// The node entity will be used for the detokening of text.
$node = $entity_type == 'node' ? $entity : NULL;
// Check if the formatter involves a link.
$href = NULL;
if ($image_link_setting = $display['settings']['image_link']) {
switch ($image_link_setting) {
case 'content':
$uri = entity_uri($entity_type, $entity);
$href = $uri['path'];
break;
case 'file':
$href = '#textimage_derivative_url#';
break;
}
}
$element = array();
if ($field['module'] == 'text') {
// Get sanitized text strings from a text field.
$text = TextimageImager::getTextFieldText($items, $field, $instance, $node);
if ($field['cardinality'] != 1 && $display['settings']['image_text_values'] == 'itemize') {
// Build separate image for each text value.
foreach ($text as $text_value) {
$element[] = array(
'#theme' => 'textimage_formatter',
'#style_name' => $display['settings']['image_style'],
'#text' => $text_value,
'#node' => $node,
'#alt' => $display['settings']['image_alt'],
'#title' => $display['settings']['image_title'],
'#href' => $href,
);
}
}
else {
// Build single image with all text values.
$element[] = array(
'#theme' => 'textimage_formatter',
'#style_name' => $display['settings']['image_style'],
'#text' => $text,
'#node' => $node,
'#alt' => $display['settings']['image_alt'],
'#title' => $display['settings']['image_title'],
'#href' => $href,
);
}
}
elseif ($field['module'] == 'image') {
// Get source image from an image field.
foreach ($items as $delta => $item) {
$source_image_file = file_load($item['fid']);
$element[$delta] = array(
'#theme' => 'textimage_formatter',
'#style_name' => $display['settings']['image_style'],
'#text' => NULL,
'#node' => $node,
'#source_image_file' => $source_image_file,
'#force_hashed_filename' => TRUE,
'#alt' => $display['settings']['image_alt'],
'#title' => $display['settings']['image_title'],
'#href' => $href,
);
}
}
return $element;
}
/**
* Implements hook_element_info().
*
* Implement a form element to enable capturing color information.
*/
function textimage_element_info() {
// This are the definition for the form API elements.
return array(
'textimage_color' => array(
'#input' => TRUE,
'#process' => array(
'textimage_color_element_process',
),
'#element_validate' => array(
'textimage_color_element_validate',
),
),
);
}
/**
* Process callback for 'textimage_color' form element.
*
* Enable capturing color information. Depending on the options, uses a normal
* textfield or a jquery_colorpicker element to capture the HEX value of a
* color.
* The following elements further qualify the process:
* '#allow_transparent' - if set to TRUE, a checkbox is displayed to set the
* color as a full transparency, In this case, color hex and opacity are
* hidden, and the value returned is NULL.
* '#allow_opacity' - if set to TRUE, a textfield is displayed to capture the
* 'opacity' value, as a percentage.
*/
function textimage_color_element_process($element, &$form_state) {
// Make sure element properties are set.
$element['#allow_transparent'] = isset($element['#allow_transparent']) ? $element['#allow_transparent'] : FALSE;
$element['#allow_opacity'] = isset($element['#allow_opacity']) ? $element['#allow_opacity'] : FALSE;
$element['#description'] = isset($element['#description']) ? $element['#description'] : NULL;
// In case default value is transparent, set hex and opacity to default
// values (white, fully opaque) so that if transparency is unchecked,
// we have a starting value.
$transparent = empty($element['#default_value']) ? TRUE : FALSE;
$hex = $transparent ? '#FFFFFF' : drupal_substr($element['#default_value'], 0, 7);
$opacity = $transparent ? 100 : _textimage_rgba_to_opacity($element['#default_value']);
if ($element['#allow_transparent'] || $element['#allow_opacity']) {
// If more sub-fields are needed to define the color, wrap them in a
// fieldset.
$element['container'] = array(
'#type' => 'fieldset',
'#description' => $element['#description'],
'#title' => $element['#title'],
);
// Checkbox for transparency.
if ($element['#allow_transparent']) {
$element['container']['transparent'] = array(
'#type' => 'checkbox',
'#title' => t('Transparent'),
'#default_value' => $transparent,
);
}
// Color field.
// Renders a jquery_colorpicker element if available and enabled, otherwise
// a textfield.
if (_textimage_get_variable('color_selector') == 'jquery_colorpicker') {
$element['container']['hex'] = array(
'#title' => t('Color'),
'#type' => 'jquery_colorpicker',
'#default_value' => drupal_substr($hex, -6),
);
}
else {
$element['container']['hex'] = array(
'#title' => t('Color'),
'#type' => 'textfield',
'#default_value' => $hex,
'#maxlength' => 7,
'#size' => 7,
'#element_validate' => array(
'image_effect_color_validate',
),
);
}
// States management for color field.
$element['container']['hex']['#states'] = array(
'visible' => array(
':input[name="' . $element['#name'] . '[container][transparent]"]' => array(
'checked' => FALSE,
),
),
);
// Textfield for opacity.
if ($element['#allow_opacity']) {
$element['container']['opacity'] = array(
'#type' => 'textfield',
'#title' => t('Opacity'),
'#default_value' => $opacity,
'#maxlength' => 3,
'#size' => 2,
'#field_suffix' => '%',
'#element_validate' => array(
'element_validate_integer',
),
'#states' => array(
'visible' => array(
':input[name="' . $element['#name'] . '[container][transparent]"]' => array(
'checked' => FALSE,
),
),
),
);
}
}
else {
// No transparency or opacity, straight color field.
if (_textimage_get_variable('color_selector') == 'jquery_colorpicker') {
$element['hex'] = array(
'#type' => 'jquery_colorpicker',
'#title' => $element['#title'],
'#description' => $element['#description'],
'#default_value' => drupal_substr($hex, -6),
);
}
else {
$element['hex'] = array(
'#type' => 'textfield',
'#title' => $element['#title'],
'#description' => $element['#description'],
'#default_value' => $hex,
'#maxlength' => 7,
'#size' => 7,
'#element_validate' => array(
'image_effect_color_validate',
),
);
}
}
unset($element['#description'], $element['#title']);
return $element;
}
/**
* Validation callback for 'textimage_color' form element.
*/
function textimage_color_element_validate(&$element, &$form_state, $form) {
// Normalize returned element values to a rgba hex value.
if ($element['#allow_transparent'] && $element['container']['transparent']['#value']) {
$element['#value'] = NULL;
}
elseif ($element['#allow_transparent'] || $element['#allow_opacity']) {
$element['#value'] = drupal_strtoupper($element['container']['hex']['#value']);
}
else {
$element['#value'] = drupal_strtoupper($element['hex']['#value']);
}
if ($element['#value'] && $element['#value'][0] != '#') {
$element['#value'] = '#' . $element['#value'];
}
if ($element['#value'] && $element['#allow_opacity']) {
$element['#value'] .= _textimage_opacity_to_alpha($element['container']['opacity']['#value']);
}
// Replace the element value in the parent form with the normalized value.
$value =& $form_state['values'];
foreach ($element['#parents'] as $path) {
$value =& $value[$path];
}
$value = $element['#value'];
}
/**
* Textimage functions.
*/
/**
* Theme function to get a Textimage from a stored image style.
*/
function theme_textimage_style_image($variables) {
return theme('textimage_formatter', array(
'style_name' => $variables['style_name'],
'text' => $variables['text'],
'format' => $variables['format'],
'caching' => $variables['caching'],
'node' => $variables['node'],
'source_image_file' => $variables['source_image_file'],
'alt' => $variables['alt'] ? $variables['alt'] : implode(' - ', $variables['text']),
'title' => $variables['title'],
'attributes' => $variables['attributes'],
));
}
/**
* Theme function to get a Textimage from a programmatical image style.
*/
function theme_textimage_direct_image($variables) {
return theme('textimage_formatter', array(
'effects' => $variables['effects'],
'text' => $variables['text'],
'format' => $variables['format'],
'caching' => $variables['caching'],
'alt' => $variables['alt'] ? $variables['alt'] : implode(' - ', $variables['text']),
'title' => $variables['title'],
'attributes' => $variables['attributes'],
));
}
/**
* Theme function to format a Textimage.
*/
function theme_textimage_formatter($variables) {
$output = NULL;
// Get URI to image file.
if ($variables['textimage'] && $variables['textimage'] instanceof Textimage) {
$image_uri = $variables['textimage']
->getUri();
}
else {
$data = array(
'style_name' => $variables['style_name'],
'effects' => $variables['effects'],
'text' => $variables['text'],
'target_uri' => $variables['target_uri'],
'extension' => $variables['format'],
'caching' => $variables['caching'],
'node' => $variables['node'],
'source_image_file' => $variables['source_image_file'],
'force_hashed_filename' => $variables['force_hashed_filename'],
);
$image = TextimageImager::getTextimage($data);
$image_uri = $image
->getUri();
}
// Render through theme_image.
if ($image_uri) {
$image_info = image_get_info($image_uri);
// Get the <img>.
$output = theme('image', array(
'path' => $image_uri,
'width' => $image_info['width'],
'height' => $image_info['height'],
'alt' => TextimageImager::processTextString($variables['alt'], NULL, $variables['node'], $variables['source_image_file']),
'title' => TextimageImager::processTextString($variables['title'], NULL, $variables['node'], $variables['source_image_file']),
'attributes' => $variables['attributes'],
));
$image_url = file_create_url($image_uri);
// Wrap the <img> in a container if requested.
if (!empty($variables['image_container_attributes'])) {
$container_attributes = array();
foreach ($variables['image_container_attributes'] as $key => $value) {
$container_attributes[$key] = str_replace('#textimage_derivative_url#', $image_url, $value);
}
$output = theme('container', array(
'element' => array(
'#attributes' => $container_attributes,
'#children' => $output,
),
));
}
// Use the output to build a link if href specified.
if ($variables['href']) {
$options['html'] = TRUE;
$href = $variables['href'] == '#textimage_derivative_url#' ? $image_url : $variables['href'];
$output = l($output, $href, $options);
}
}
return $output;
}
/**
* Deliver directly a Textimage from the URL request.
*/
function textimage_url_deliver() {
// Get the real directory of the public wrapper.
$public_path = file_stream_wrapper_get_instance_by_scheme('public')
->getDirectoryPath();
// Full path to public textimage files.
$public_textimage_path = base_path() . $public_path . '/textimage/';
$pattern = '/' . str_replace('/', '\\/', $public_textimage_path) . '/';
// The request in format [style]/[Text_0]/[Text_1]/.../[Text_n].[extension]
// is in the trailing part of the URL.
$trail = urldecode(preg_replace($pattern, '', request_uri()));
$args = explode('/', $trail);
// Manages the [style].
$style_name = array_shift($args);
$style = TextimageStyles::get($style_name);
if (!$style) {
drupal_not_found();
}
if ($style['textimage']['uri_scheme'] != 'public') {
drupal_access_denied();
}
// [Text_0]/[Text_1]/.../[Text_n] to the $text array.
$text = $args;
// Manage the [extension].
$last_text = array_pop($text);
$offset = strrpos($last_text, '.');
if ($offset && strlen($last_text) - $offset <= 5) {
$extension = substr($last_text, $offset + 1);
$text[] = substr($last_text, 0, $offset);
}
else {
$extension = 'png';
$text[] = $last_text;
}
// Get the image and transfer to client.
$uri = TextimageImager::processImageRequest($style, NULL, $text, $extension);
$image_info = image_get_info($uri);
file_transfer($uri, array(
'Content-Type' => $image_info['mime_type'],
'Content-Length' => $image_info['file_size'],
));
}
/**
* Render a text string, color formatted.
*
* Optionally, uses Luma algorithms to determine best color match
* for foreground and border colors.
*/
function theme_textimage_colored_string($variables) {
drupal_add_css(drupal_get_path('module', 'textimage') . '/misc/css/textimage.admin.css');
// Set background color.
if (!empty($variables['background_color'])) {
$background_color = drupal_substr($variables['background_color'], 0, 7);
$background_color_css = "background-color:{$background_color};";
}
else {
$background_color = "#FFFFFF";
$background_color_css = NULL;
}
// Set text.
$text = $variables['text'];
// Set text foreground color. If 'matchLuma' is specified, resolves
// best color against background.
if ($variables['foreground_color'] == 'matchLuma') {
$foreground_color = textimage_match_luma($background_color);
}
else {
$foreground_color = drupal_substr($variables['foreground_color'], 0, 7);
}
// Set border css if required. If 'matchLuma' is specified for border
// color, resolves best color against background.
$border_css = NULL;
if ($variables['border']) {
if ($variables['border_color'] == 'matchLuma') {
$border_color = textimage_match_luma($background_color);
}
else {
$border_color = drupal_substr($variables['border_color'], 0, 7);
}
$border_css = "border-color:{$border_color};";
}
return "<span class=\"textimage-colored-string\" style=\"{$background_color_css} color:{$foreground_color}; {$border_css} \">{$text}</span>";
}
/**
* Determine best match to over/underlay a defined color.
*
* Calculates UCCIR 601 luma of the entered color and returns a black or
* white color to ensure readibility.
*
* @see http://en.wikipedia.org/wiki/Luma_video
*/
function textimage_match_luma($rgba, $soft = FALSE) {
list($r, $g, $b) = array_values(imagecache_actions_hex2rgba($rgba));
$luma = 1 - (0.299 * $r + 0.587 * $g + 0.114 * $b) / 255;
if ($luma < 0.5) {
// Bright colors - black.
$d = 0;
}
else {
// Dark colors - white.
$d = 255;
}
return _color_pack(array(
$d,
$d,
$d,
));
}
/**
* Display/log a diagnostic message.
*
* @param string $message
* message
* @param int $severity
* severity as per watchdog()
* @param string $caller
* the calling function
*/
function _textimage_diag($message, $severity, $caller = NULL, $user_messages = TRUE) {
if ($caller) {
$message = t("@message - Function: @caller", array(
'@message' => $message,
'@caller' => $caller,
));
}
if ($severity <= WATCHDOG_NOTICE) {
watchdog('textimage', $message, array(), $severity);
}
if ($severity <= variable_get('textimage_message_level', WATCHDOG_WARNING) && $user_messages) {
switch ($severity) {
case WATCHDOG_DEBUG:
case WATCHDOG_INFO:
case WATCHDOG_NOTICE:
$type = 'status';
break;
case WATCHDOG_WARNING:
$type = 'warning';
break;
default:
$type = 'error';
}
drupal_set_message($message, $type, FALSE);
}
}
/**
* Return a 'textimage' configuration variable.
*
* @param string $variable
* textimage settings variable to be returned, or NULL
* to return the entire config.
*
* @return string|array
* value of the requested configuration variable, or the entire array
* if no variable specified in input
*/
function _textimage_get_variable($variable = NULL) {
$vars =& drupal_static(__FUNCTION__);
if (!isset($vars)) {
$vars = variable_get('textimage', array());
$vars = drupal_array_merge_deep(array(
'store_scheme' => 'private',
'fonts_handling_module' => 'textimage',
'fonts_path' => 'private://textimage_store/fonts',
'default_font' => array(
'name' => '',
'uri' => '',
),
'backgrounds_handling_module' => 'textimage',
'backgrounds_path' => 'private://textimage_store/backgrounds',
'color_selector' => 'textbox',
), $vars);
}
if ($variable) {
return isset($vars[$variable]) ? $vars[$variable] : NULL;
}
else {
return $vars;
}
}
/**
* Store a 'textimage' configuration variable.
*
* @param string|array $variable
* the name of the textimage configuration variable, or the entire
* configuration array
* @param string $value
* the value of the textimage configuration variable to store
*/
function _textimage_set_variable($variable, $value = NULL) {
if (is_array($variable)) {
$vars = $variable;
}
else {
$vars = _textimage_get_variable();
if ($variable) {
$vars[$variable] = $value;
}
}
$vars = array_intersect_key($vars, array(
'store_scheme' => NULL,
'fonts_handling_module' => NULL,
'fonts_path' => NULL,
'default_font' => array(),
'backgrounds_handling_module' => NULL,
'backgrounds_path' => NULL,
'color_selector' => NULL,
));
variable_set('textimage', $vars);
drupal_static_reset('_textimage_get_variable');
}
/**
* Helper - check if a module is enabled and at a specified release level.
*
* @param string $module
* Module name.
* @param string $version
* (optional) Module version.
* @param string $comparison_operator
* (optional) A comparison operator to test against $version.
*
* @return bool
* TRUE if module is enabled, FALSE otherwise.
*/
function _textimage_module_exists($module, $version = NULL, $comparison_operator = '>=') {
if (!module_exists($module)) {
return FALSE;
}
if ($version) {
$module_info = system_get_info('module', $module);
if (empty($module_info['version'])) {
return TRUE;
}
return version_compare($module_info['version'], $version, $comparison_operator);
}
return TRUE;
}
/**
* Convert RGBA alpha to percent opacity.
*
* @param string $rgba
* RGBA hex.
*
* @return int
* Opacity as percentage (0 = transparent, 100 = fully opaque).
*/
function _textimage_rgba_to_opacity($rgba) {
$hex = drupal_substr($rgba, 7, 2);
return $hex ? floor(-(hexdec($hex) - 127) / 127 * 100) : 100;
}
/**
* Convert percent opacity to hex alpha.
*
* @param int $value
* Opacity as percentage (0 = transparent, 100 = fully opaque).
*
* @return string
* Opacity as HEX.
*/
function _textimage_opacity_to_alpha($value) {
return $value == NULL ? NULL : drupal_strtoupper(str_pad(dechex(-($value - 100) / 100 * 127), 2, "0", STR_PAD_LEFT));
}
/**
* Cleanup Textimage.
*
* This will remove all image files generated via Textimage, flush all
* the image styles, clear all cache and all store entries on the db.
*/
function _textimage_flush_all() {
foreach (image_styles() as $style) {
if (TextimageStyles::isTextimage($style)) {
image_style_flush($style);
}
}
if (file_exists(_textimage_get_store_path('unstyled_hashed'))) {
file_unmanaged_delete_recursive(_textimage_get_store_path('unstyled_hashed'));
}
if (file_exists(_textimage_get_store_path('uncached'))) {
file_unmanaged_delete_recursive(_textimage_get_store_path('uncached'));
}
cache_clear_all(NULL, 'cache_textimage');
db_truncate('textimage_store')
->execute();
_textimage_diag(t('All Textimage images were removed.'), WATCHDOG_NOTICE);
}
/**
* Return a path within the textimage_store structure.
*/
function _textimage_get_store_path($path) {
return _textimage_get_variable('store_scheme') . '://textimage_store/' . $path;
}
/**
* Load Textimage toolkit dependent functions.
*/
function _textimage_load_toolkit_functions() {
// Include toolkit specific image functions.
$toolkit_functions_filename = dirname(__FILE__) . '/effects/textimage_text.' . image_get_toolkit() . '.inc';
if (is_file($toolkit_functions_filename)) {
require_once $toolkit_functions_filename;
return TRUE;
}
else {
$toolkits = image_get_available_toolkits();
_textimage_diag(t("Textimage does not support the '@toolkit' image toolkit.", array(
'@toolkit' => $toolkits[image_get_toolkit()],
)), WATCHDOG_ERROR);
return FALSE;
}
}
Functions
Constants
Name | Description |
---|---|
TEXTIMAGE_FONTYOURFACE_MIN_VERSION | Define constants. |
TEXTIMAGE_JQUERY_COLORPICKER_MIN_VERSION | |
TEXTIMAGE_MEDIA_MIN_VERSION | |
TEXTIMAGE_TOKEN_MIN_VERSION |