SF.net SVN: docutils:[9933 ] trunk/docutils

milde--- via Docutils-checkins <[email protected]>
Newsgroups gmane.text.docutils.cvs
Message-ID <[email protected]>
Revision: 9933
          http://sourceforge.net/p/docutils/code/9933
Author:   milde
Date:     2024-09-20 06:30:59 +0000 (Fri, 20 Sep 2024)
Log Message:
-----------
Revise/fix handling of length specification in the ODT writer.

Use "px" as fallback unit for unitless image size attributes.

Fix conversion factor of "pc" (pica) to "cm".

Fix conversion of image width in "%" if the height is specified.

Adjust fallback DPI value (currently not used) to match CSS units.

Document that PIL/Pillow is always required if images are inserted
without specifying width and height, also if "scale" is not used.

Modified Paths:
--------------
    trunk/docutils/HISTORY.rst
    trunk/docutils/docs/user/odt.rst
    trunk/docutils/docutils/writers/odf_odt/__init__.py

Modified: trunk/docutils/HISTORY.rst
===================================================================
--- trunk/docutils/HISTORY.rst	2024-09-19 10:20:44 UTC (rev 9932)
+++ trunk/docutils/HISTORY.rst	2024-09-20 06:30:59 UTC (rev 9933)
@@ -181,6 +181,13 @@
 
   - `null.Writer.translate()` sets `self.output` to the empty string.
 
+* docutils/writers/odf_odt/__init__.py
+
+  - Use "px" as fallback unit for unitless image size attributes.
+  - Fix conversion factor of "pc" (pica) to "cm".
+  - Fix conversion of image width in "%" if the height is specified.
+  - Adjust fallback DPI value (currently not used) to match CSS units.
+
 * tools/rst2odt.py
 
   - Use `core.publish_file()` instead of `core.publish_file_to_binary()`.

Modified: trunk/docutils/docs/user/odt.rst
===================================================================
--- trunk/docutils/docs/user/odt.rst	2024-09-19 10:20:44 UTC (rev 9932)
+++ trunk/docutils/docs/user/odt.rst	2024-09-20 06:30:59 UTC (rev 9933)
@@ -39,8 +39,8 @@
   highlighting of code in literal blocks.  See section `Syntax
   highlighting`_.
 
-- Optional -- `Python Imaging Library`_ (PIL) is required if on an
-  image or figure directive, you specify ``scale`` but not ``width``
+- Optional -- `Python Imaging Library`_ (PIL/Pillow_) is required if
+  you use the image or figure directive but don't specify ``width``
   and ``height``.  See section `Images and figures`_.
 
 
@@ -975,23 +975,21 @@
 Images and figures
 ------------------
 
-If on the image or the figure directive you provide the scale option
-but do not provide the width and height options, then ``odtwriter``
-will attempt to determine the size of the image using the `Python
-Imaging Library`_ (PIL).  If ``odtwriter`` cannot find and import
+The ODT Writer only supports fixed `length units`_ ("cm", "mm", "in",
+"pc", "pt", "px) for the size attributes "width", and "height".
+The fallback unit (used for attribute values without unit) is "px".
+
+If on the image or the figure directive you do not provide the width
+and height options, then ``odtwriter`` will attempt to determine the
+size of the image using the Python Imaging Library (PIL/Pillow_).
+If ``odtwriter`` cannot find and import the
 Python Imaging Library, it will raise an exception.  If this
 ocurrs, you can fix it by doing one of the following:
 
 - Install the Python Imaging Library or
 
-- Remove the ``scale`` option or
-
 - Add both the ``width`` and the ``height`` options.
 
-So, the rule is: if on any image or figure, you specify scale but
-not both width and height, you must install the `Python Imaging
-Library`_ library.
-
 For more information about PIL, see: `Python Imaging Library`_.
 
 
@@ -1188,6 +1186,8 @@
     tools.html#rst2odt
 .. _reStructuredText:
     ../ref/rst/restructuredtext.html
+.. _length units:
+    ../ref/rst/restructuredtext.html#length-units
 .. _`OpenDocument Text`:
     https://en.wikipedia.org/wiki/OpenDocument
 .. _LibreOffice:
@@ -1196,3 +1196,4 @@
     https://pygments.org/
 .. _`Python Imaging Library`:
     https://en.wikipedia.org/wiki/Python_Imaging_Library
+.. _`Pillow`: https://pypi.org/project/pillow/

Modified: trunk/docutils/docutils/writers/odf_odt/__init__.py
===================================================================
--- trunk/docutils/docutils/writers/odf_odt/__init__.py	2024-09-19 10:20:44 UTC (rev 9932)
+++ trunk/docutils/docutils/writers/odf_odt/__init__.py	2024-09-20 06:30:59 UTC (rev 9933)
@@ -2207,6 +2207,7 @@
                     'Invalid %s for image: "%s".  '
                     'Error: "%s".' % (
                         attr, node.attributes[attr], exp))
+                size, unit = 0.5, 'cm'  # fallback to avoid consequential error
         return size, unit
 
     def convert_to_cm(self, size):
@@ -2223,13 +2224,15 @@
         elif size.endswith('pt'):
             size = float(size[:-2]) * 0.035     # convert pt to cm
         elif size.endswith('pc'):
-            size = float(size[:-2]) * 2.371     # convert pc to cm
+            size = float(size[:-2]) * 0.423     # convert pc to cm
         elif size.endswith('mm'):
             size = float(size[:-2]) * 0.1       # convert mm to cm
         elif size.endswith('cm'):
             size = float(size[:-2])
+        elif size[-1:] in '0123456789.':        # no unit, use px
+            size = float(size) * 0.026          # convert px to cm
         else:
-            raise ValueError('unknown unit type')
+            raise ValueError('unit not supported with ODT')
         unit = 'cm'
         return size, unit
 
@@ -2250,8 +2253,12 @@
         scale = self.get_image_scale(node)
         width, width_unit = self.get_image_width_height(node, 'width')
         height, _ = self.get_image_width_height(node, 'height')
-        dpi = (72, 72)
-        if PIL is not None and source in self.image_dict:
+        dpi = (96, 96)  # image resolution in pixel per inch
+        if width is None or height is None:
+            if PIL is None:
+                raise RuntimeError(
+                    'image size not fully specified and PIL not installed')
+            # TODO: catch error and warn (similar to unsupported units).
             filename, destination = self.image_dict[source]
             with PIL.Image.open(filename, 'r') as img:
                 img_size = img.size
@@ -2261,26 +2268,19 @@
                 iter(dpi)
             except TypeError:
                 dpi = (dpi, dpi)
-        else:
-            img_size = None
-        if width is None or height is None:
-            if img_size is None:
-                raise RuntimeError(
-                    'image size not fully specified and PIL not installed')
-            if width is None:
-                width = img_size[0]
-                width = float(width) * 0.026        # convert px to cm
+            # TODO: use dpi when converting px to cm
+        if width is None:
+            width = img_size[0] * 0.026             # convert px to cm
+        if height is None and width_unit != '%':
+            height = img_size[1] * 0.026            # convert px to cm
+        if width_unit == '%':
+            factor = width
+            line_width = self.get_page_width()
+            width = factor * line_width
             if height is None:
-                height = img_size[1]
-                height = float(height) * 0.026      # convert px to cm
-            if width_unit == '%':
-                factor = width
-                image_width = img_size[0]
-                image_width = float(image_width) * 0.026    # convert px to cm
-                image_height = img_size[1]
-                image_height = float(image_height) * 0.026  # convert px to cm
-                line_width = self.get_page_width()
-                width = factor * line_width
+                # scale proportionally
+                image_width = img_size[0] * 0.026   # convert px to cm
+                image_height = img_size[1] * 0.026  # convert px to cm
                 factor = (factor * line_width) / image_width
                 height = factor * image_height
         width *= scale

This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.