1
1
mirror of https://github.com/Kozea/WeasyPrint.git synced 2024-08-17 00:20:42 +03:00

add drawing border

This commit is contained in:
Salem Harrache 2011-08-05 11:31:16 +02:00
parent 1dcf13c580
commit 97d78d1205
8 changed files with 200 additions and 38 deletions

2
.gitignore vendored
View File

@ -1,3 +1,5 @@
*.pyc
*.egg-info
.coverage
weasy/tests/test_web/website/static/*result*

View File

@ -23,6 +23,7 @@ import pangocairo
from .css.computed_values import LENGTHS_TO_PIXELS
from .formatting_structure import boxes
from . import text
import math
class CairoContext(cairo.Context):
"""
@ -39,6 +40,111 @@ class CairoContext(cairo.Context):
color.red / 255., color.green / 255., color.blue / 255.,
color.alpha)
class Point(object):
def __init__(self, x, y):
self.x = round(x)
self.y = round(y)
def __repr__(self):
return '<%s (%d, %d)>' % (type(self).__name__, self.x, self.y)
def move_to(self, x, y):
self.x +=x
self.y +=y
def copy(self):
"""Return copy of the point."""
cls = type(self)
return cls(self.x, self.y)
class Line(object):
def __init__(self, point1, point2):
self.first_point = point1
self.second_point = point2
self.type = "solid"
def __repr__(self):
return '<%s (%s, %s)>' % (type(self).__name__, self.first_point,
self.second_point)
def translate(self, x, y):
self.first_point.move(x, y)
self.second_point.move(x, y)
@property
def length(self):
diff_x = self.second_point.x - self.first_point.x
diff_y = self.second_point.y - self.first_point.y
return math.sqrt(math.pow(diff_x, 2) + math.pow(diff_y, 2))
def draw_path(self, context):
context.move_to(self.first_point.x, self.first_point.y)
context.line_to(self.second_point.x, self.second_point.y)
def copy(self):
"""Return copy of the line."""
cls = type(self)
return cls(self.first_point.copy(), self.second_point.copy())
class Trapezoid(object):
def __init__(self, line1, line2):
if line1.length > line2.length:
self.long_base = line1
self.small_base = line2
else:
self.long_base = line2
self.small_base = line1
def __repr__(self):
return '<%s (%s, %s)>' % (type(self).__name__, self.small_base,
self.small_base)
def get_points(self):
return [self.long_base.first_point, self.small_base.first_point,
self.small_base.second_point, self.long_base.second_point]
def get_all_lines(self):
points = list(self.get_points())
n = len (points)
for i, point in enumerate(points):
yield Line(points[i], points[(i+1)%n])
def get_side_lines(self):
points = list(self.get_points())
n = len (points)
for i, point in enumerate(points):
if i % 2 == 0:
yield Line(points[i], points[(i+1)%n])
def get_middle_line(self):
if self.long_base.first_point.x != self.long_base.second_point.x:
x1 = self.long_base.first_point.x
x2 = self.long_base.second_point.x
else:
x1 = (self.long_base.first_point.x + self.small_base.first_point.x)
x1 = x1 / 2.
x2 = x1
if self.long_base.first_point.y != self.long_base.second_point.y:
y1 = self.long_base.first_point.y
y2 = self.long_base.second_point.y
else:
y1 = (self.long_base.first_point.y + self.small_base.first_point.y)
y1 = y1 / 2.
y2 = y1
return Line(Point(x1,y1), Point(x2, y2))
def draw_path(self, context):
for i, line in enumerate(self.get_all_lines()):
if i == 0:
context.move_to(line.first_point.x, line.first_point.y)
context.line_to(line.second_point.x, line.second_point.y)
def translate(self, x, y):
self.first_point.translate(x, y)
self.second_point.translate(x, y)
def draw_background(context, box):
bg_color = box.style['background-color'][0]
if bg_color.alpha > 0:
@ -50,6 +156,68 @@ def draw_background(context, box):
context.set_source_colorvalue(bg_color)
context.fill()
def draw_border(context, box):
"""
Draw the box border to a Cairo context.
"""
# TODO: implement border-spacing, border-collapse and the other border style
def get_edge(x, y, width, height):
return (Point(x,y), Point(x+width,y), Point(x+width, y+height),
Point(x, y+height))
def get_border_area():
# border area
x = box.position_x + box.margin_left
y = box.position_y + box.margin_top
border_edge = get_edge(x, y, box.border_width(), box.border_height())
# padding area
x = x + box.border_left_width
y = y + box.border_top_width
padding_edge = get_edge(x, y, box.padding_width(), box.padding_height())
return border_edge, padding_edge
def get_lines(rectangle):
n = len (rectangle)
for i, point in enumerate(rectangle):
yield Line(rectangle[i], rectangle[(i+1) % n])
def get_trapezoids():
border_edge, padding_edge = get_border_area()
for line1,line2 in zip(get_lines(border_edge), get_lines(padding_edge)):
yield Trapezoid(line1, line2)
def draw_border_side(side, trapezoid):
width = float(box.style['border-%s-width'%side][0].value)
if box.style['border-%s-width'%side] == 0:
return
color = box.style['border-%s-color'%side][0]
style = box.style['border-%s-style'%side][0].value
if color.alpha > 0:
context.save()
if not style in ["dotted", "dashed"]:
trapezoid.draw_path(context)
context.clip()
elif style == "dotted":
#TODO:Find a way to make a dotted border
context.set_dash([width], 0)
elif style == "dashed":
#TODO:Find a way to make a dashed border
context.set_dash([4*width], 0)
line = trapezoid.get_middle_line()
line.draw_path(context)
context.set_source_colorvalue(color)
context.set_line_width(width)
context.stroke()
context.restore()
trapezoids_side = zip(["top", "right", "bottom", "left"], get_trapezoids())
for side, trapezoid in trapezoids_side:
draw_border_side(side, trapezoid)
def draw_text(context, textbox):
"""
Draw the given TextBox to a Cairo context from Pangocairo Context
@ -67,6 +235,8 @@ def draw_box(context, box):
for child in box.children:
draw_box(context, child)
if box.border_left_width > 0:
draw_border(context, box)
def draw_page(page, context):
"""
@ -74,6 +244,7 @@ def draw_page(page, context):
"""
draw_box(context, page.root_box)
def draw_page_to_png(page, surface):
"""
Draw the given PageBox to a PNG file.

View File

@ -36,16 +36,10 @@ compute_dimensions.register(boxes.BlockBox)(
@compute_dimensions.register(boxes.LineBox)
def line_dimensions(box):
# TODO: real line box height
# box.height = box.style.line_height
# box.height = 0
resolve_percentages(box)
@compute_dimensions.register(boxes.InlineBox)
def inlinebox_dimensions(box):
# TODO: real line box height
# box.height = box.style.line_height
# box.height = 0
resolve_percentages(box)
def page_dimensions(box):

View File

@ -339,7 +339,16 @@ class LineBoxFormatting(object):
def compute_dimensions(self, box):
"""Add the width and height in the linebox."""
if isinstance(box, boxes.InlineBox) or isinstance(box, boxes.LineBox):
if isinstance(box, boxes.LineBox):
widths = []
heights = []
for child in box.children:
self.compute_dimensions(child)
widths.append(child.width)
heights.append(child.height)
box.width = sum(widths)
box.height = max(heights)
elif isinstance(box, boxes.InlineBox):
widths = []
heights = []
for child in box.children:
@ -413,12 +422,8 @@ class LineBoxFormatting(object):
for child in self.flatten_tree(child, depth):
resolve_percentages(child)
yield child
elif isinstance(child, boxes.TextBox):
else:
child.depth = depth
resolve_percentages(child)
yield child
elif isinstance(child, boxes.InlineBlockBox):
raise NotImplementedError
elif isinstance(child, boxes.InlineLevelReplacedBox):
raise NotImplementedError

View File

@ -15,6 +15,13 @@ def index():
@app.route('/', methods=("POST",))
def post():
content = request.values.get("content", "").strip("\r\n").strip(" ")
# Save the input HTML
item = g.kalamar.open('files',{"name":"input.html"})
item['data'].write(content)
item.save()
pdf_document = PDFDocument.from_string(content)
pdf_document.do_layout()
pdf_document.draw()
@ -33,12 +40,7 @@ def post():
item['data'].write(pdf_document.output.getvalue())
item.save()
# Save the input HTML
item = g.kalamar.open('files',{"name":"input.html"})
item['data'].write(content)
item.save()
image = png_document.get_png_data()
return render_template('index.html.jinja2', content=content, image=image)

View File

@ -1,21 +1,17 @@
<style>
html {
background-color:#CACACA;
background-color:gray;
font-family: DejaVu Sans Mono;
font-size:15px;
}
p {
width:600px;
margin:auto;
}
.salem {
color:blue;
}
.melinda {
color:#FF4500;
width:480px;
margin:40px;
padding: 10px;
border-width:20px;
vertical-align:middle;
border-width:1px;
border-style:solid;
}
h1 {
@ -23,13 +19,5 @@ h1 {
}
</style>
<h1>Avancement de weasyprint</h1>
<span style="font-size:200px; background-color:red;">R</span>
<p><em>WeasyPrint</em> is very <strong>coooll !!!</strong> </p>
<p class="salem">Salem : Bon je teste avec une seule page, et de "weasyprinter" en png.La page est générée par weasyprint. Trop cool non?</p>
<p class="salem" style="text-decoration : line-through;">Bon il y a pas les retours à la ligne, mais avec ca serait parfait pour cette semaine xD.</p>
<p class="melinda">Mélinda : Cette semaine ou celle d'après, t'as le temps xD</p>
<p class="salem">Salem : Ben non, j'ai promis pour midi, j'ai tenu promesse. MOUAHAHAHHA !!!</p>
<p>test test <img src="http://img41.xooimage.com/files/5/f/5/477876-2877733.jpg" border="1" alt=""/></p>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB