Commit 704939bf authored by Fabien Morin's avatar Fabien Morin

- change the way the image is replaced : use the image "as she is display", so

  if the image is display as a thumbnail, the image will be added in the odg
  document as thumbnail size/quality
- _replaceImage method is not required anymore, remove it
- update methods signatures to be consistent with other render_*
- if there is some height and width in the node attribute (because of
  attr_dict), try to make the image smaller or equal to this dimentions, and
  keep proportion

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@31496 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 858e08e9
...@@ -32,13 +32,20 @@ from Products.Formulator.DummyField import fields ...@@ -32,13 +32,20 @@ from Products.Formulator.DummyField import fields
from lxml.etree import Element from lxml.etree import Element
from Acquisition import aq_base from Acquisition import aq_base
from lxml import etree from lxml import etree
from decimal import Decimal
import re
DRAW_URI = 'urn:oasis:names:tc:opendocument:xmlns:drawing:1.0' DRAW_URI = 'urn:oasis:names:tc:opendocument:xmlns:drawing:1.0'
TEXT_URI = 'urn:oasis:names:tc:opendocument:xmlns:text:1.0' TEXT_URI = 'urn:oasis:names:tc:opendocument:xmlns:text:1.0'
XLINK_URI = 'http://www.w3.org/1999/xlink'
SVG_URI = 'urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0'
NSMAP = { NSMAP = {
'draw': DRAW_URI, 'draw': DRAW_URI,
'text': TEXT_URI, 'text': TEXT_URI,
'xlink': XLINK_URI,
'svg': SVG_URI
} }
class ImageFieldWidget(Widget.TextWidget): class ImageFieldWidget(Widget.TextWidget):
...@@ -102,44 +109,8 @@ class ImageFieldWidget(Widget.TextWidget): ...@@ -102,44 +109,8 @@ class ImageFieldWidget(Widget.TextWidget):
extra=extra, extra=extra,
) )
def _replaceImage(self, image_frame_node, ooo_builder, image_field, def render_odg(self, field, value, as_string, ooo_builder, REQUEST,
printout, REQUEST, attr_dict): render_prefix, attr_dict):
"""
Replace the image in an odg file using an ERP5Form image field.
return True if the image have been found, else return False
"""
image_node = image_frame_node.getchildren()[0]
path = '/'.join(REQUEST.physicalPathFromURL(image_field.get_value('default')))
if path in (None, ''):
# not possible to add image, remove the existing one
image_frame_node = image_node.getparent()
image_frame_node.remove(image_node)
return False
path = path.encode()
image_object = image_field.getPortalObject().restrictedTraverse(path)
image_parameter_dict = {
'display': image_field.get_value('image_display'),
'format': image_field.get_value('image_format')
}
picture_type, image_data = image_object.convert(**image_parameter_dict)
if image_data is None:
# not possible to add image, remove the existing one
image_frame_node = image_node.getparent()
image_frame_node.remove(image_node)
return False
picture_path = printout._createOdfUniqueFileName(path=path,
picture_type=picture_type)
ooo_builder.addFileEntry(picture_path, media_type=picture_type, content=image_data)
width, height = printout._getPictureSize(image_object, image_node)
image_node.set('{%s}href' % image_node.nsmap['xlink'], picture_path)
image_frame_node.set('{%s}width' % image_node.nsmap['svg'], width)
image_frame_node.set('{%s}height' % image_node.nsmap['svg'], height)
attr_dict.setdefault(image_node.tag, {}).update(image_node.attrib)
attr_dict.setdefault(image_frame_node.tag, {}).update(image_frame_node.attrib)
return True
def render_odg(self, field, as_string, local_name, target_node, printout,
REQUEST, ooo_builder, attr_dict=None):
""" """
return an image xml node rendered in odg format return an image xml node rendered in odg format
if as_string is True (default) the returned value is a string (xml if as_string is True (default) the returned value is a string (xml
...@@ -147,34 +118,88 @@ class ImageFieldWidget(Widget.TextWidget): ...@@ -147,34 +118,88 @@ class ImageFieldWidget(Widget.TextWidget):
object. object.
attr_dict can be used for additional parameters (like style). attr_dict can be used for additional parameters (like style).
""" """
# replace the image in the odg document
if not self._replaceImage(target_node, ooo_builder, field, printout,
REQUEST, attr_dict):
# if image is not found, return None
return None
if attr_dict is None: if attr_dict is None:
attr_dict = {} attr_dict = {}
draw_frame_node = None
if value in ('', None):
return None
path = '/'.join(REQUEST.physicalPathFromURL(value))
path = path.encode()
image_object = field.getPortalObject().restrictedTraverse(path)
display = field.get_value('image_display')
format = field.get_value('image_format')
image_parameter_dict = { 'display': display,
'format':format}
# convert the image using fields parameters. In this way, if an image
# is displayed in the form as a thumbnail, it will be added in the odg
# document as thumbnail size/quality
content_type, image_data = image_object.convert(**image_parameter_dict)
if image_data is None:
return draw_frame_node
format = content_type.split('/')[-1]
# add the image to the odg document
picture_path = ooo_builder.addImage(image=image_data, format=format)
# create the xml nodes related to the image
draw_frame_tag_name = '{%s}%s' % (DRAW_URI, 'frame') draw_frame_tag_name = '{%s}%s' % (DRAW_URI, 'frame')
draw_frame_node = Element(draw_frame_tag_name, nsmap=NSMAP) draw_frame_node = Element(draw_frame_tag_name, nsmap=NSMAP)
draw_frame_node.attrib.update(attr_dict.get(draw_frame_tag_name, {})) draw_frame_node.attrib.update(attr_dict.get(draw_frame_tag_name,
{}).pop(0))
draw_image_tag_name = '{%s}%s' % (DRAW_URI, 'image')
draw_image_node = Element(draw_image_tag_name, nsmap=NSMAP) # set the size of the image
draw_image_node.attrib.update(attr_dict.get(draw_image_tag_name, {})) if display is not None:
height, width = image_object.getSizeFromImageDisplay(display)
text_p_tag_name = '{%s}%s' % (TEXT_URI, local_name) if draw_frame_node.attrib.get('{%s}width' % SVG_URI, {}) != {} and \
text_p_node = Element(text_p_tag_name, nsmap=NSMAP) draw_frame_node.attrib.get('{%s}height' % SVG_URI, {}) != {}:
text_p_node.attrib.update(attr_dict.get(text_p_tag_name, {})) # if a size already exist from attr_dict, try to resize the image to
# fit this size (image should not be biger than size from attr_dict)
draw_image_node.append(text_p_node) # devide the value by 20 to have cm instead of px
draw_frame_node.append(draw_image_node) width, height = self._getPictureSize(width/20., height/20.,
target_width=draw_frame_node.attrib.get('{%s}width' % SVG_URI, {}),
target_height=draw_frame_node.attrib.get('{%s}height' % SVG_URI, {}))
draw_frame_node.set('{%s}width' % SVG_URI, str(width))
draw_frame_node.set('{%s}height' % SVG_URI, str(height))
image_tag_name = '{%s}%s' % (DRAW_URI, 'image')
image_node = Element(image_tag_name, nsmap=NSMAP)
image_node.attrib.update(attr_dict.get(image_tag_name, {}).pop())
image_node.set('{%s}href' % XLINK_URI, picture_path)
draw_frame_node.append(image_node)
if as_string: if as_string:
return etree.tostring(draw_frame_node) return etree.tostring(draw_frame_node)
return draw_frame_node return draw_frame_node
def _getPictureSize(self, picture_width, picture_height, target_width,
target_height):
# if not match causes exception
width_tuple = re.match("(\d[\d\.]*)(.*)", target_width).groups()
height_tuple = re.match("(\d[\d\.]*)(.*)", target_height).groups()
unit = width_tuple[1]
w = float(width_tuple[0])
h = float(height_tuple[0])
aspect_ratio = 1
try: # try image properties
aspect_ratio = picture_width / picture_height
except (TypeError, ZeroDivisionError):
try: # try ERP5.Document.Image API
height = picture_height
if height:
aspect_ratio = picture_width / height
except AttributeError: # fallback to Photo API
height = float(picture_height)
if height:
aspect_ratio = picture_width / height
resize_w = h * aspect_ratio
resize_h = w / aspect_ratio
if resize_w < w:
w = resize_w
elif resize_h < h:
h = resize_h
return (str(w) + unit, str(h) + unit)
ImageFieldWidgetInstance = ImageFieldWidget() ImageFieldWidgetInstance = ImageFieldWidget()
ImageFieldValidatorInstance = Validator.StringValidator() ImageFieldValidatorInstance = Validator.StringValidator()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment