mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-31 14:33:54 -04:00
Handle non-solid pens
This commit is contained in:
parent
9f13e30737
commit
0dd9c26dbe
@ -109,7 +109,6 @@ class PdfEngine(QPaintEngine):
|
|||||||
|
|
||||||
def init_page(self):
|
def init_page(self):
|
||||||
self.pdf.transform(self.pdf_system)
|
self.pdf.transform(self.pdf_system)
|
||||||
self.pdf.set_rgb_colorspace()
|
|
||||||
self.graphics.reset()
|
self.graphics.reset()
|
||||||
self.pdf.save_stack()
|
self.pdf.save_stack()
|
||||||
self.current_page_inited = True
|
self.current_page_inited = True
|
||||||
|
@ -15,7 +15,7 @@ from PyQt4.Qt import (
|
|||||||
|
|
||||||
from calibre.ebooks.pdf.render.common import (
|
from calibre.ebooks.pdf.render.common import (
|
||||||
Name, Array, fmtnum, Stream, Dictionary)
|
Name, Array, fmtnum, Stream, Dictionary)
|
||||||
from calibre.ebooks.pdf.render.serialize import Path, Color
|
from calibre.ebooks.pdf.render.serialize import Path
|
||||||
|
|
||||||
def convert_path(path): # {{{
|
def convert_path(path): # {{{
|
||||||
p = Path()
|
p = Path()
|
||||||
@ -392,8 +392,6 @@ class Graphics(object):
|
|||||||
return color, opacity, pattern, do_fill
|
return color, opacity, pattern, do_fill
|
||||||
|
|
||||||
def apply_stroke(self, state, pdf_system, painter):
|
def apply_stroke(self, state, pdf_system, painter):
|
||||||
# TODO: Handle pens with non solid brushes by setting the colorspace
|
|
||||||
# for stroking to a pattern
|
|
||||||
# TODO: Support miter limit by using QPainterPathStroker
|
# TODO: Support miter limit by using QPainterPathStroker
|
||||||
pen = state.stroke
|
pen = state.stroke
|
||||||
self.pending_state.do_stroke = True
|
self.pending_state.do_stroke = True
|
||||||
@ -427,14 +425,10 @@ class Graphics(object):
|
|||||||
pdf.current_page.write(' 0 d ')
|
pdf.current_page.write(' 0 d ')
|
||||||
|
|
||||||
# Stroke fill
|
# Stroke fill
|
||||||
b = pen.brush()
|
color, opacity, pattern, self.pending_state.do_stroke = self.convert_brush(
|
||||||
vals = list(b.color().getRgbF())
|
pen.brush(), state.brush_origin, state.opacity, pdf_system,
|
||||||
vals[-1] *= state.opacity
|
painter.transform())
|
||||||
color = Color(*vals)
|
self.pdf.apply_stroke(color, pattern, opacity)
|
||||||
pdf.set_stroke_color(color)
|
|
||||||
|
|
||||||
if vals[-1] < 1e-5 or b.style() == Qt.NoBrush:
|
|
||||||
self.pending_state.do_stroke = False
|
|
||||||
|
|
||||||
def apply_fill(self, state, pdf_system, painter):
|
def apply_fill(self, state, pdf_system, painter):
|
||||||
self.pending_state.do_fill = True
|
self.pending_state.do_fill = True
|
||||||
@ -458,7 +452,7 @@ class Graphics(object):
|
|||||||
the brush origin before painting an object. While not perfect, this is
|
the brush origin before painting an object. While not perfect, this is
|
||||||
better than nothing.
|
better than nothing.
|
||||||
'''
|
'''
|
||||||
if not self.current_state.do_fill:
|
if not hasattr(self, 'last_fill') or not self.current_state.do_fill:
|
||||||
return
|
return
|
||||||
|
|
||||||
if isinstance(self.last_fill.brush, TexturePattern):
|
if isinstance(self.last_fill.brush, TexturePattern):
|
||||||
|
@ -10,7 +10,6 @@ __docformat__ = 'restructuredtext en'
|
|||||||
import hashlib
|
import hashlib
|
||||||
from future_builtins import map
|
from future_builtins import map
|
||||||
from itertools import izip
|
from itertools import izip
|
||||||
from collections import namedtuple
|
|
||||||
|
|
||||||
from PyQt4.Qt import QBuffer, QByteArray, QImage, Qt, QColor, qRgba
|
from PyQt4.Qt import QBuffer, QByteArray, QImage, Qt, QColor, qRgba
|
||||||
|
|
||||||
@ -23,8 +22,6 @@ from calibre.ebooks.pdf.render.links import Links
|
|||||||
|
|
||||||
PDFVER = b'%PDF-1.3'
|
PDFVER = b'%PDF-1.3'
|
||||||
|
|
||||||
Color = namedtuple('Color', 'red green blue opacity')
|
|
||||||
|
|
||||||
class IndirectObjects(object):
|
class IndirectObjects(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -353,9 +350,6 @@ class PDFStream(object):
|
|||||||
cm = ' '.join(map(fmtnum, vals))
|
cm = ' '.join(map(fmtnum, vals))
|
||||||
self.current_page.write_line(cm + ' cm')
|
self.current_page.write_line(cm + ' cm')
|
||||||
|
|
||||||
def set_rgb_colorspace(self):
|
|
||||||
self.current_page.write_line('/DeviceRGB CS /DeviceRGB cs')
|
|
||||||
|
|
||||||
def save_stack(self):
|
def save_stack(self):
|
||||||
self.current_page.write_line('q')
|
self.current_page.write_line('q')
|
||||||
|
|
||||||
@ -391,13 +385,11 @@ class PDFStream(object):
|
|||||||
def serialize(self, o):
|
def serialize(self, o):
|
||||||
serialize(o, self.current_page)
|
serialize(o, self.current_page)
|
||||||
|
|
||||||
def set_stroke_color(self, color):
|
def set_stroke_opacity(self, opacity):
|
||||||
opacity = color.opacity
|
|
||||||
if opacity not in self.stroke_opacities:
|
if opacity not in self.stroke_opacities:
|
||||||
op = Dictionary({'Type':Name('ExtGState'), 'CA': opacity})
|
op = Dictionary({'Type':Name('ExtGState'), 'CA': opacity})
|
||||||
self.stroke_opacities[opacity] = self.objects.add(op)
|
self.stroke_opacities[opacity] = self.objects.add(op)
|
||||||
self.current_page.set_opacity(self.stroke_opacities[opacity])
|
self.current_page.set_opacity(self.stroke_opacities[opacity])
|
||||||
self.current_page.write_line(' '.join(map(fmtnum, color[:3])) + ' SC')
|
|
||||||
|
|
||||||
def set_fill_opacity(self, opacity):
|
def set_fill_opacity(self, opacity):
|
||||||
opacity = float(opacity)
|
opacity = float(opacity)
|
||||||
@ -518,17 +510,27 @@ class PDFStream(object):
|
|||||||
serialize(Name(name), self.current_page)
|
serialize(Name(name), self.current_page)
|
||||||
self.current_page.write_line(' Do Q')
|
self.current_page.write_line(' Do Q')
|
||||||
|
|
||||||
|
def apply_color_space(self, color, pattern, stroke=False):
|
||||||
|
wl = self.current_page.write_line
|
||||||
|
if color is not None and pattern is None:
|
||||||
|
wl(' '.join(map(fmtnum, color)) + (' RG' if stroke else ' rg'))
|
||||||
|
elif color is None and pattern is not None:
|
||||||
|
wl('/Pattern %s /%s %s'%('CS' if stroke else 'cs', pattern,
|
||||||
|
'SCN' if stroke else 'scn'))
|
||||||
|
elif color is not None and pattern is not None:
|
||||||
|
col = ' '.join(map(fmtnum, color))
|
||||||
|
wl('/PCSp %s %s /%s %s'%('CS' if stroke else 'cs', col, pattern,
|
||||||
|
'SCN' if stroke else 'scn'))
|
||||||
|
|
||||||
def apply_fill(self, color=None, pattern=None, opacity=None):
|
def apply_fill(self, color=None, pattern=None, opacity=None):
|
||||||
if opacity is not None:
|
if opacity is not None:
|
||||||
self.set_fill_opacity(opacity)
|
self.set_fill_opacity(opacity)
|
||||||
wl = self.current_page.write_line
|
self.apply_color_space(color, pattern)
|
||||||
if color is not None and pattern is None:
|
|
||||||
wl(' '.join(map(fmtnum, color)) + ' rg')
|
def apply_stroke(self, color=None, pattern=None, opacity=None):
|
||||||
elif color is None and pattern is not None:
|
if opacity is not None:
|
||||||
wl('/Pattern cs /%s scn'%pattern)
|
self.set_stroke_opacity(opacity)
|
||||||
elif color is not None and pattern is not None:
|
self.apply_color_space(color, pattern, stroke=True)
|
||||||
col = ' '.join(map(fmtnum, color))
|
|
||||||
wl('/PCSp cs %s /%s scn'%(col, pattern))
|
|
||||||
|
|
||||||
def end(self):
|
def end(self):
|
||||||
if self.current_page.getvalue():
|
if self.current_page.getvalue():
|
||||||
|
@ -12,7 +12,7 @@ from tempfile import gettempdir
|
|||||||
|
|
||||||
from PyQt4.Qt import (QBrush, QColor, QPoint, QPixmap, QPainterPath, QRectF,
|
from PyQt4.Qt import (QBrush, QColor, QPoint, QPixmap, QPainterPath, QRectF,
|
||||||
QApplication, QPainter, Qt, QImage, QLinearGradient,
|
QApplication, QPainter, Qt, QImage, QLinearGradient,
|
||||||
QPointF)
|
QPointF, QPen)
|
||||||
QBrush, QColor, QPoint, QPixmap, QPainterPath, QRectF, Qt, QPointF
|
QBrush, QColor, QPoint, QPixmap, QPainterPath, QRectF, Qt, QPointF
|
||||||
|
|
||||||
from calibre.ebooks.pdf.render.engine import PdfDevice
|
from calibre.ebooks.pdf.render.engine import PdfDevice
|
||||||
@ -69,6 +69,14 @@ def full(p, xmax, ymax):
|
|||||||
g.setColorAt(1, QColor('#fff'))
|
g.setColorAt(1, QColor('#fff'))
|
||||||
p.fillRect(x, y, w, w, QBrush(g))
|
p.fillRect(x, y, w, w, QBrush(g))
|
||||||
|
|
||||||
|
pen = QPen(QBrush(Qt.blue))
|
||||||
|
pen.setWidth(xmax/3)
|
||||||
|
p.setPen(pen)
|
||||||
|
x += w + w/10
|
||||||
|
y += w
|
||||||
|
p.drawLine(x, y, x+w, y)
|
||||||
|
|
||||||
|
|
||||||
def run(dev, func):
|
def run(dev, func):
|
||||||
p = QPainter(dev)
|
p = QPainter(dev)
|
||||||
if isinstance(dev, PdfDevice):
|
if isinstance(dev, PdfDevice):
|
||||||
@ -91,12 +99,18 @@ def brush(p, xmax, ymax):
|
|||||||
|
|
||||||
p.fillRect(0, y+xmax/1.9, w, w, QBrush(pix))
|
p.fillRect(0, y+xmax/1.9, w, w, QBrush(pix))
|
||||||
|
|
||||||
|
def pen(p, xmax, ymax):
|
||||||
|
pix = QPixmap(I('console.png'))
|
||||||
|
pen = QPen(QBrush(pix), 60)
|
||||||
|
p.setPen(pen)
|
||||||
|
p.drawRect(0, xmax/3, xmax/3, xmax/2)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
app = QApplication([])
|
app = QApplication([])
|
||||||
app
|
app
|
||||||
tdir = gettempdir()
|
tdir = gettempdir()
|
||||||
pdf = os.path.join(tdir, 'painter.pdf')
|
pdf = os.path.join(tdir, 'painter.pdf')
|
||||||
func = full
|
func = pen
|
||||||
dpi = 100
|
dpi = 100
|
||||||
with open(pdf, 'wb') as f:
|
with open(pdf, 'wb') as f:
|
||||||
dev = PdfDevice(f, xdpi=dpi, ydpi=dpi, compress=False)
|
dev = PdfDevice(f, xdpi=dpi, ydpi=dpi, compress=False)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user