@@ -19,16 +19,17 @@ def audit_primitives(primitives, width, height, fonts):
|
||||
if any(abs(a - b) > 0.001 for a, b in zip((actual.left, actual.top, actual.right, actual.bottom), (item.box.left, item.box.top, item.box.right, item.box.bottom))):
|
||||
raise generator.engraving.types.EngravingError(f'{item.sources}: glyph bounds disagree with its actual outline')
|
||||
|
||||
def audit_layout(document: dict, layout: generator.engraving.types.LayoutDocument, fonts: generator.engraving.fonts.Fonts) -> None:
|
||||
def audit_layout(document: dict, layout: generator.engraving.types.LayoutDocument, fonts: generator.engraving.fonts.Fonts, *, systems_per_page: int | None = 2) -> None:
|
||||
index = generator.engraving.notation.ScoreIndex(document)
|
||||
fragments, primitives = {}, {}
|
||||
previous_end = fractions.Fraction()
|
||||
scale = layout.pages[0].systems[0].scale
|
||||
for page in layout.pages:
|
||||
if len(page.systems) != 2 and (page is not layout.pages[-1] or len(page.systems) != 1):
|
||||
if not page.systems or (systems_per_page is not None and len(page.systems) != systems_per_page and (page is not layout.pages[-1] or not 1 <= len(page.systems) < systems_per_page)):
|
||||
raise generator.engraving.types.EngravingError('pages must contain two music systems, except an odd final system')
|
||||
if len(page.systems) == 2 and page.systems[0].box.bottom + layout.style.system_gap > page.systems[1].box.top + 0.01:
|
||||
raise generator.engraving.types.EngravingError('music systems overlap their page rows')
|
||||
for first, second in zip(page.systems, page.systems[1:]):
|
||||
if first.box.bottom + layout.style.system_gap > second.box.top + 0.01:
|
||||
raise generator.engraving.types.EngravingError('music systems overlap their page rows')
|
||||
audit_primitives(page.primitives, page.width, page.height, fonts)
|
||||
header = generator.engraving.types.bounds([p for p in page.primitives if p.role in ('title', 'subtitle')])
|
||||
footer = generator.engraving.types.bounds([p for p in page.primitives if p.role == 'page_number'])
|
||||
|
||||
@@ -30,12 +30,14 @@ class OutlinePen(fontTools.pens.basePen.BasePen):
|
||||
def _endPath(self):
|
||||
pass
|
||||
|
||||
def rasterize_page(page: generator.engraving.types.Page, fonts: generator.engraving.fonts.Fonts) -> PIL.Image.Image:
|
||||
return rasterize_band(page, page.primitives, 0, page.height, fonts)
|
||||
def rasterize_page(page: generator.engraving.types.Page, fonts: generator.engraving.fonts.Fonts, *, ink=None, background=None, output_scale=1) -> PIL.Image.Image:
|
||||
return rasterize_band(page, page.primitives, 0, page.height, fonts, ink=ink, background=background, output_scale=output_scale)
|
||||
|
||||
def rasterize_band(page: generator.engraving.types.Page, primitives: tuple[generator.engraving.types.Primitive, ...], top: int, bottom: int, fonts: generator.engraving.fonts.Fonts) -> PIL.Image.Image:
|
||||
scale = page.supersampling
|
||||
image = PIL.Image.new('RGB', (page.width * scale, (bottom - top) * scale), generator.theme.rgb('background'))
|
||||
def rasterize_band(page: generator.engraving.types.Page, primitives: tuple[generator.engraving.types.Primitive, ...], top: int, bottom: int, fonts: generator.engraving.fonts.Fonts, *, ink=None, background=None, output_scale=1) -> PIL.Image.Image:
|
||||
ink = generator.theme.rgb('ink') if ink is None else ink
|
||||
background = generator.theme.rgb('background') if background is None else background
|
||||
scale = page.supersampling * output_scale
|
||||
image = PIL.Image.new('RGB', (round(page.width * scale), round((bottom - top) * scale)), background)
|
||||
context = aggdraw.Draw(image)
|
||||
for item in primitives:
|
||||
points = [(x * scale, y * scale - top * scale) for x, y in item.points]
|
||||
@@ -56,16 +58,18 @@ def rasterize_band(page: generator.engraving.types.Page, primitives: tuple[gener
|
||||
if item.kind == 'polygon':
|
||||
path.close()
|
||||
if item.kind in ('glyph', 'polygon'):
|
||||
context.path(path, None, aggdraw.Brush(generator.theme.rgb('ink')))
|
||||
context.path(path, None, aggdraw.Brush(ink))
|
||||
else:
|
||||
context.path(path, aggdraw.Pen(generator.theme.rgb('ink'), item.thickness * scale))
|
||||
context.path(path, aggdraw.Pen(ink, item.thickness * scale))
|
||||
context.flush()
|
||||
drawing = PIL.ImageDraw.Draw(image)
|
||||
for item in primitives:
|
||||
if item.kind == 'text':
|
||||
x, y = item.points[0]
|
||||
drawing.text((x * scale, y * scale - top * scale), item.value, font=fonts.text_font(item.size * scale), anchor='ls', fill=generator.theme.rgb('ink'))
|
||||
return image.resize((page.width, bottom - top), PIL.Image.Resampling.LANCZOS)
|
||||
drawing.text((x * scale, y * scale - top * scale), item.value, font=fonts.text_font(item.size * scale), anchor='ls', fill=ink)
|
||||
result = image.resize((round(page.width * output_scale), round((bottom - top) * output_scale)), PIL.Image.Resampling.LANCZOS)
|
||||
image.close()
|
||||
return result
|
||||
|
||||
@dataclasses.dataclass(frozen=True)
|
||||
class Band:
|
||||
|
||||
Reference in New Issue
Block a user