mirror of
https://github.com/Kozea/WeasyPrint.git
synced 2024-10-05 08:27:22 +03:00
Cache images to avoid downloading them over and over.
(In particular, page background images were downloaded for each page.)
This commit is contained in:
parent
91f4ad1dba
commit
fc4c4863df
@ -34,6 +34,7 @@ from .css.computed_values import LENGTHS_TO_PIXELS
|
|||||||
from .formatting_structure.build import build_formatting_structure
|
from .formatting_structure.build import build_formatting_structure
|
||||||
from .layout import layout
|
from .layout import layout
|
||||||
from . import draw
|
from . import draw
|
||||||
|
from .draw import helpers as draw_helpers
|
||||||
from . import utils
|
from . import utils
|
||||||
|
|
||||||
|
|
||||||
@ -67,6 +68,7 @@ class Document(object):
|
|||||||
self._computed_styles = None
|
self._computed_styles = None
|
||||||
self._formatting_structure = None
|
self._formatting_structure = None
|
||||||
self._pages = None
|
self._pages = None
|
||||||
|
self._image_cache = {}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def base_url(self):
|
def base_url(self):
|
||||||
@ -142,6 +144,18 @@ class Document(object):
|
|||||||
self._pages = layout(self)
|
self._pages = layout(self)
|
||||||
return self._pages
|
return self._pages
|
||||||
|
|
||||||
|
def get_image_surface_from_uri(self, uri):
|
||||||
|
if uri in self._image_cache:
|
||||||
|
return self._image_cache[uri]
|
||||||
|
try:
|
||||||
|
surface = draw_helpers.get_image_surface_from_uri(uri)
|
||||||
|
# TODO: have a more specific list of exception for network errors
|
||||||
|
# and PNG parsing errors.
|
||||||
|
except Exception:
|
||||||
|
surface = None
|
||||||
|
self._image_cache[uri] = surface
|
||||||
|
return surface
|
||||||
|
|
||||||
|
|
||||||
class PNGDocument(Document):
|
class PNGDocument(Document):
|
||||||
"""PNG output document."""
|
"""PNG output document."""
|
||||||
|
@ -161,11 +161,8 @@ def draw_background(context, box, clip=True):
|
|||||||
if bg_image.type != 'URI':
|
if bg_image.type != 'URI':
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
surface = box.document.get_image_surface_from_uri(bg_image.absoluteUri)
|
||||||
surface = get_image_surface_from_uri(bg_image.absoluteUri)
|
if surface is None:
|
||||||
# TODO: have a more specific list of exception for network errors
|
|
||||||
# and PNG parsing errors.
|
|
||||||
except Exception:
|
|
||||||
return
|
return
|
||||||
|
|
||||||
image_width = surface.get_width()
|
image_width = surface.get_width()
|
||||||
|
@ -118,14 +118,20 @@ def add_list_marker(box):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
image = box.style.list_style_image
|
image = box.style.list_style_image
|
||||||
if get_single_keyword(image) == 'none':
|
if get_single_keyword(image) != 'none':
|
||||||
|
# surface may be None here too, in case the image is not available.
|
||||||
|
surface = box.document.get_image_surface_from_uri(image[0].absoluteUri)
|
||||||
|
else:
|
||||||
|
surface = None
|
||||||
|
|
||||||
|
if surface is None:
|
||||||
type_ = get_single_keyword(box.style.list_style_type)
|
type_ = get_single_keyword(box.style.list_style_type)
|
||||||
if type_ == 'none':
|
if type_ == 'none':
|
||||||
return
|
return
|
||||||
marker = GLYPH_LIST_MARKERS[type_]
|
marker = GLYPH_LIST_MARKERS[type_]
|
||||||
marker_box = boxes.TextBox(box.document, box.element, marker)
|
marker_box = boxes.TextBox(box.document, box.element, marker)
|
||||||
else:
|
else:
|
||||||
replacement = html.ImageReplacement(image[0].absoluteUri)
|
replacement = html.ImageReplacement(surface)
|
||||||
marker_box = boxes.ImageMarkerBox(
|
marker_box = boxes.ImageMarkerBox(
|
||||||
box.document, box.element, replacement)
|
box.document, box.element, replacement)
|
||||||
|
|
||||||
|
@ -117,11 +117,11 @@ def handle_img(document, element):
|
|||||||
src = get_url_attribute(element, 'src')
|
src = get_url_attribute(element, 'src')
|
||||||
alt = element.get('alt')
|
alt = element.get('alt')
|
||||||
if src:
|
if src:
|
||||||
try:
|
surface = document.get_image_surface_from_uri(src)
|
||||||
replacement = ImageReplacement(src)
|
if surface is not None:
|
||||||
# TODO: have a more specific list of exception for network errors
|
replacement = ImageReplacement(surface)
|
||||||
# and image parsing errors.
|
return make_replaced_box(document, element, replacement)
|
||||||
except Exception:
|
else:
|
||||||
# Invalid image, use the alt-text.
|
# Invalid image, use the alt-text.
|
||||||
if alt:
|
if alt:
|
||||||
return make_text_box(document, element, alt)
|
return make_text_box(document, element, alt)
|
||||||
@ -133,8 +133,6 @@ def handle_img(document, element):
|
|||||||
# TODO: find some indicator that an image is missing.
|
# TODO: find some indicator that an image is missing.
|
||||||
# For now, just remove the image.
|
# For now, just remove the image.
|
||||||
return None
|
return None
|
||||||
else:
|
|
||||||
return make_replaced_box(document, element, replacement)
|
|
||||||
else:
|
else:
|
||||||
if alt:
|
if alt:
|
||||||
return make_text_box(document, element, alt)
|
return make_text_box(document, element, alt)
|
||||||
@ -172,11 +170,11 @@ class Replacement(object):
|
|||||||
class ImageReplacement(Replacement):
|
class ImageReplacement(Replacement):
|
||||||
"""Replaced ``<img>`` element.
|
"""Replaced ``<img>`` element.
|
||||||
|
|
||||||
:param image_uri: uri where to get the image.
|
:param surface: a cairo :class:`ImageSurface` object.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def __init__(self, image_uri):
|
def __init__(self, surface):
|
||||||
self.surface = get_image_surface_from_uri(image_uri)
|
self.surface = surface
|
||||||
|
|
||||||
def intrinsic_width(self):
|
def intrinsic_width(self):
|
||||||
if self.surface:
|
if self.surface:
|
||||||
|
Loading…
Reference in New Issue
Block a user