adding more fonts
All checks were successful
Python CI / test (3.10) (push) Successful in 2m2s
Python CI / test (3.12) (push) Successful in 1m52s
Python CI / test (3.13) (push) Successful in 1m47s

This commit is contained in:
Duncan Tourolle 2025-11-09 21:17:26 +01:00
parent 849ba2f60f
commit 2b14517344
18 changed files with 769 additions and 2 deletions

View File

@ -0,0 +1,227 @@
"""
Demonstration of bundled fonts in pyWebLayout.
This example shows:
1. How to use the bundled DejaVu font families
2. Different font variants (regular, bold, italic, bold-italic)
3. The three font families (Sans, Serif, Monospace)
4. Convenient Font.from_family() method for easy font selection
The demo creates a page showcasing all bundled fonts with different styles.
"""
from pyWebLayout.concrete import Page
from pyWebLayout.abstract import Paragraph, Word
from pyWebLayout.style import Font, FontWeight, FontStyle, BundledFont
from pyWebLayout.style.page_style import PageStyle
from pyWebLayout.layout.document_layouter import DocumentLayouter
def create_font_showcase_page():
"""
Create a page demonstrating all bundled fonts and variants.
"""
# Create page with some padding
page = Page(size=(800, 1000), style=PageStyle(border_width=20))
layouter = DocumentLayouter(page)
# Title
title_font = Font.from_family(
BundledFont.SANS,
font_size=32,
colour=(0, 0, 100),
weight=FontWeight.BOLD
)
title = Paragraph(title_font)
title.add_word(Word("Bundled", title_font))
title.add_word(Word("Fonts", title_font))
title.add_word(Word("Showcase", title_font))
layouter.layout_paragraph(title)
page._current_y_offset += 20
# Introduction
intro_font = Font.from_family(BundledFont.SANS, font_size=14, colour=(50, 50, 50))
intro = Paragraph(intro_font)
intro_text = "pyWebLayout bundles the DejaVu font family with three font types and four variants each."
for word in intro_text.split():
intro.add_word(Word(word, intro_font))
layouter.layout_paragraph(intro)
page._current_y_offset += 25
# --- Sans Serif Section ---
section_font = Font.from_family(
BundledFont.SANS,
font_size=20,
colour=(0, 100, 0),
weight=FontWeight.BOLD
)
sans_section = Paragraph(section_font)
sans_section.add_word(Word("Sans-Serif", section_font))
sans_section.add_word(Word("(DejaVu", section_font))
sans_section.add_word(Word("Sans)", section_font))
layouter.layout_paragraph(sans_section)
page._current_y_offset += 10
# Sans Regular
sans_regular = Font.from_family(BundledFont.SANS, font_size=16)
demo_text_paragraph(layouter, page, sans_regular, "Regular:")
# Sans Bold
sans_bold = Font.from_family(BundledFont.SANS, font_size=16, weight=FontWeight.BOLD)
demo_text_paragraph(layouter, page, sans_bold, "Bold:")
# Sans Italic
sans_italic = Font.from_family(BundledFont.SANS, font_size=16, style=FontStyle.ITALIC)
demo_text_paragraph(layouter, page, sans_italic, "Italic:")
# Sans Bold Italic
sans_bold_italic = Font.from_family(
BundledFont.SANS,
font_size=16,
weight=FontWeight.BOLD,
style=FontStyle.ITALIC
)
demo_text_paragraph(layouter, page, sans_bold_italic, "Bold Italic:")
page._current_y_offset += 20
# --- Serif Section ---
serif_section = Paragraph(section_font)
serif_section.add_word(Word("Serif", section_font))
serif_section.add_word(Word("(DejaVu", section_font))
serif_section.add_word(Word("Serif)", section_font))
layouter.layout_paragraph(serif_section)
page._current_y_offset += 10
# Serif Regular
serif_regular = Font.from_family(BundledFont.SERIF, font_size=16)
demo_text_paragraph(layouter, page, serif_regular, "Regular:")
# Serif Bold
serif_bold = Font.from_family(BundledFont.SERIF, font_size=16, weight=FontWeight.BOLD)
demo_text_paragraph(layouter, page, serif_bold, "Bold:")
# Serif Italic
serif_italic = Font.from_family(BundledFont.SERIF, font_size=16, style=FontStyle.ITALIC)
demo_text_paragraph(layouter, page, serif_italic, "Italic:")
# Serif Bold Italic
serif_bold_italic = Font.from_family(
BundledFont.SERIF,
font_size=16,
weight=FontWeight.BOLD,
style=FontStyle.ITALIC
)
demo_text_paragraph(layouter, page, serif_bold_italic, "Bold Italic:")
page._current_y_offset += 20
# --- Monospace Section ---
mono_section = Paragraph(section_font)
mono_section.add_word(Word("Monospace", section_font))
mono_section.add_word(Word("(DejaVu", section_font))
mono_section.add_word(Word("Sans", section_font))
mono_section.add_word(Word("Mono)", section_font))
layouter.layout_paragraph(mono_section)
page._current_y_offset += 10
# Mono Regular
mono_regular = Font.from_family(BundledFont.MONOSPACE, font_size=14)
demo_code_paragraph(layouter, page, mono_regular, "Regular:")
# Mono Bold
mono_bold = Font.from_family(BundledFont.MONOSPACE, font_size=14, weight=FontWeight.BOLD)
demo_code_paragraph(layouter, page, mono_bold, "Bold:")
# Mono Italic
mono_italic = Font.from_family(BundledFont.MONOSPACE, font_size=14, style=FontStyle.ITALIC)
demo_code_paragraph(layouter, page, mono_italic, "Italic:")
# Mono Bold Italic
mono_bold_italic = Font.from_family(
BundledFont.MONOSPACE,
font_size=14,
weight=FontWeight.BOLD,
style=FontStyle.ITALIC
)
demo_code_paragraph(layouter, page, mono_bold_italic, "Bold Italic:")
page._current_y_offset += 20
# Footer
footer_font = Font.from_family(BundledFont.SANS, font_size=12, colour=(100, 100, 100))
footer = Paragraph(footer_font)
footer_text = "All fonts are free and open source under the Bitstream Vera License."
for word in footer_text.split():
footer.add_word(Word(word, footer_font))
layouter.layout_paragraph(footer)
return page
def demo_text_paragraph(layouter, page, font, label):
"""Create a paragraph showing sample text with the given font."""
# Label in smaller font
label_font = Font.from_family(BundledFont.SANS, font_size=12, colour=(100, 100, 100))
label_para = Paragraph(label_font)
label_para.add_word(Word(label, label_font))
layouter.layout_paragraph(label_para)
page._current_y_offset += 5
# Sample text
para = Paragraph(font)
sample = "The quick brown fox jumps over the lazy dog. 0123456789"
for word in sample.split():
para.add_word(Word(word, font))
layouter.layout_paragraph(para)
page._current_y_offset += 8
def demo_code_paragraph(layouter, page, font, label):
"""Create a paragraph showing sample code with the given font."""
# Label in smaller font
label_font = Font.from_family(BundledFont.SANS, font_size=12, colour=(100, 100, 100))
label_para = Paragraph(label_font)
label_para.add_word(Word(label, label_font))
layouter.layout_paragraph(label_para)
page._current_y_offset += 5
# Sample code
para = Paragraph(font)
code = "def hello(): print('Hello, World!') # 0123456789"
for word in code.split():
para.add_word(Word(word, font))
layouter.layout_paragraph(para)
page._current_y_offset += 8
if __name__ == "__main__":
print("\n")
print("=" * 70)
print("Bundled Fonts Demonstration")
print("=" * 70)
print()
print("Creating font showcase page...")
page = create_font_showcase_page()
print("Rendering page...")
image = page.render()
output_file = "demo_08_bundled_fonts.png"
image.save(output_file)
print(f"Saved: {output_file}")
print()
print("=" * 70)
print("Demo complete!")
print()
print("The page showcases all bundled fonts:")
print(" - DejaVu Sans (Sans-serif)")
print(" - DejaVu Serif (Serif)")
print(" - DejaVu Sans Mono (Monospace)")
print()
print("Each family has 4 variants:")
print(" - Regular")
print(" - Bold")
print(" - Italic")
print(" - Bold Italic")
print("=" * 70)
print()

View File

@ -0,0 +1,187 @@
Fonts are (c) Bitstream (see below). DejaVu changes are in public domain.
Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below)
Bitstream Vera Fonts Copyright
------------------------------
Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is
a trademark of Bitstream, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of the fonts accompanying this license ("Fonts") and associated
documentation files (the "Font Software"), to reproduce and distribute the
Font Software, including without limitation the rights to use, copy, merge,
publish, distribute, and/or sell copies of the Font Software, and to permit
persons to whom the Font Software is furnished to do so, subject to the
following conditions:
The above copyright and trademark notices and this permission notice shall
be included in all copies of one or more of the Font Software typefaces.
The Font Software may be modified, altered, or added to, and in particular
the designs of glyphs or characters in the Fonts may be modified and
additional glyphs or characters may be added to the Fonts, only if the fonts
are renamed to names not containing either the words "Bitstream" or the word
"Vera".
This License becomes null and void to the extent applicable to Fonts or Font
Software that has been modified and is distributed under the "Bitstream
Vera" names.
The Font Software may be sold as part of a larger software package but no
copy of one or more of the Font Software typefaces may be sold by itself.
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME
FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING
ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE
FONT SOFTWARE.
Except as contained in this notice, the names of Gnome, the Gnome
Foundation, and Bitstream Inc., shall not be used in advertising or
otherwise to promote the sale, use or other dealings in this Font Software
without prior written authorization from the Gnome Foundation or Bitstream
Inc., respectively. For further information, contact: fonts at gnome dot
org.
Arev Fonts Copyright
------------------------------
Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of the fonts accompanying this license ("Fonts") and
associated documentation files (the "Font Software"), to reproduce
and distribute the modifications to the Bitstream Vera Font Software,
including without limitation the rights to use, copy, merge, publish,
distribute, and/or sell copies of the Font Software, and to permit
persons to whom the Font Software is furnished to do so, subject to
the following conditions:
The above copyright and trademark notices and this permission notice
shall be included in all copies of one or more of the Font Software
typefaces.
The Font Software may be modified, altered, or added to, and in
particular the designs of glyphs or characters in the Fonts may be
modified and additional glyphs or characters may be added to the
Fonts, only if the fonts are renamed to names not containing either
the words "Tavmjong Bah" or the word "Arev".
This License becomes null and void to the extent applicable to Fonts
or Font Software that has been modified and is distributed under the
"Tavmjong Bah Arev" names.
The Font Software may be sold as part of a larger software package but
no copy of one or more of the Font Software typefaces may be sold by
itself.
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL
TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
Except as contained in this notice, the name of Tavmjong Bah shall not
be used in advertising or otherwise to promote the sale, use or other
dealings in this Font Software without prior written authorization
from Tavmjong Bah. For further information, contact: tavmjong @ free
. fr.
TeX Gyre DJV Math
-----------------
Fonts are (c) Bitstream (see below). DejaVu changes are in public domain.
Math extensions done by B. Jackowski, P. Strzelczyk and P. Pianowski
(on behalf of TeX users groups) are in public domain.
Letters imported from Euler Fraktur from AMSfonts are (c) American
Mathematical Society (see below).
Bitstream Vera Fonts Copyright
Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera
is a trademark of Bitstream, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of the fonts accompanying this license (“Fonts”) and associated
documentation
files (the “Font Software”), to reproduce and distribute the Font Software,
including without limitation the rights to use, copy, merge, publish,
distribute,
and/or sell copies of the Font Software, and to permit persons to whom
the Font Software is furnished to do so, subject to the following
conditions:
The above copyright and trademark notices and this permission notice
shall be
included in all copies of one or more of the Font Software typefaces.
The Font Software may be modified, altered, or added to, and in particular
the designs of glyphs or characters in the Fonts may be modified and
additional
glyphs or characters may be added to the Fonts, only if the fonts are
renamed
to names not containing either the words “Bitstream” or the word “Vera”.
This License becomes null and void to the extent applicable to Fonts or
Font Software
that has been modified and is distributed under the “Bitstream Vera”
names.
The Font Software may be sold as part of a larger software package but
no copy
of one or more of the Font Software typefaces may be sold by itself.
THE FONT SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME
FOUNDATION
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL,
SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN
ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR
INABILITY TO USE
THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
Except as contained in this notice, the names of GNOME, the GNOME
Foundation,
and Bitstream Inc., shall not be used in advertising or otherwise to promote
the sale, use or other dealings in this Font Software without prior written
authorization from the GNOME Foundation or Bitstream Inc., respectively.
For further information, contact: fonts at gnome dot org.
AMSFonts (v. 2.2) copyright
The PostScript Type 1 implementation of the AMSFonts produced by and
previously distributed by Blue Sky Research and Y&Y, Inc. are now freely
available for general use. This has been accomplished through the
cooperation
of a consortium of scientific publishers with Blue Sky Research and Y&Y.
Members of this consortium include:
Elsevier Science IBM Corporation Society for Industrial and Applied
Mathematics (SIAM) Springer-Verlag American Mathematical Society (AMS)
In order to assure the authenticity of these fonts, copyright will be
held by
the American Mathematical Society. This is not meant to restrict in any way
the legitimate use of the fonts, such as (but not limited to) electronic
distribution of documents containing these fonts, inclusion of these fonts
into other public domain or commercial font collections or computer
applications, use of the outline data to create derivative fonts and/or
faces, etc. However, the AMS does require that the AMS copyright notice be
removed from any derivative versions of the fonts which have been altered in
any way. In addition, to ensure the fidelity of TeX documents using Computer
Modern fonts, Professor Donald Knuth, creator of the Computer Modern faces,
has requested that any alterations which yield different font metrics be
given a different name.
$Id$

View File

@ -0,0 +1,67 @@
[![Build Status](https://travis-ci.org/dejavu-fonts/dejavu-fonts.svg)](https://travis-ci.org/dejavu-fonts/dejavu-fonts)
DejaVu fonts 2.37 (c)2004-2016 DejaVu fonts team
------------------------------------------------
The DejaVu fonts are a font family based on the Bitstream Vera Fonts
(http://gnome.org/fonts/). Its purpose is to provide a wider range of
characters (see status.txt for more information) while maintaining the
original look and feel.
DejaVu fonts are based on Bitstream Vera fonts version 1.10.
Available fonts (Sans = sans serif, Mono = monospaced):
DejaVu Sans Mono
DejaVu Sans Mono Bold
DejaVu Sans Mono Bold Oblique
DejaVu Sans Mono Oblique
DejaVu Sans
DejaVu Sans Bold
DejaVu Sans Bold Oblique
DejaVu Sans Oblique
DejaVu Sans ExtraLight (experimental)
DejaVu Serif
DejaVu Serif Bold
DejaVu Serif Bold Italic (experimental)
DejaVu Serif Italic (experimental)
DejaVu Sans Condensed (experimental)
DejaVu Sans Condensed Bold (experimental)
DejaVu Sans Condensed Bold Oblique (experimental)
DejaVu Sans Condensed Oblique (experimental)
DejaVu Serif Condensed (experimental)
DejaVu Serif Condensed Bold (experimental)
DejaVu Serif Condensed Bold Italic (experimental)
DejaVu Serif Condensed Italic (experimental)
DejaVu Math TeX Gyre
All fonts are also available as derivative called DejaVu LGC with support
only for Latin, Greek and Cyrillic scripts.
For license information see LICENSE. What's new is described in NEWS. Known
bugs are in BUGS. All authors are mentioned in AUTHORS.
Fonts are published in source form as SFD files (Spline Font Database from
FontForge - http://fontforge.sf.net/) and in compiled form as TTF files
(TrueType fonts).
For more information go to http://dejavu.sourceforge.net/.
Characters from Arev fonts, Copyright (c) 2006 by Tavmjong Bah:
---------------------------
U+01BA, U+01BF, U+01F7, U+021C-U+021D, U+0220, U+0222-U+0223,
U+02B9, U+02BA, U+02BD, U+02C2-U+02C5, U+02d4-U+02D5,
U+02D7, U+02EC-U+02EE, U+0346-U+034E, U+0360, U+0362,
U+03E2-03EF, U+0460-0463, U+0466-U+0486, U+0488-U+0489, U+04A8-U+04A9,
U+0500-U+050F, U+2055-205E, U+20B0, U+20B2-U+20B3, U+2102, U+210D, U+210F,
U+2111, U+2113, U+2115, U+2118-U+211A, U+211C-U+211D, U+2124, U+2135,
U+213C-U+2140, U+2295-U+2298, U+2308-U+230B, U+26A2-U+26B1, U+2701-U+2704,
U+2706-U+2709, U+270C-U+274B, U+2758-U+275A, U+2761-U+2775, U+2780-U+2794,
U+2798-U+27AF, U+27B1-U+27BE, U+FB05-U+FB06
DejaVu Math TeX Gyre
--------------------
TeX Gyre DJV Math by B. Jackowski, P. Strzelczyk and P. Pianowski
(on behalf of TeX users groups).
$Id$

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,129 @@
# Bundled Fonts
This directory contains free, open-source TrueType fonts bundled with pyWebLayout for consistent rendering across all platforms.
## Font Families
### DejaVu Sans (Sans-serif)
A modern, clean sans-serif font excellent for body text and UI elements.
- `DejaVuSans.ttf` - Regular
- `DejaVuSans-Bold.ttf` - Bold
- `DejaVuSans-Oblique.ttf` - Italic
- `DejaVuSans-BoldOblique.ttf` - Bold Italic
### DejaVu Serif (Serif)
A classic serif font ideal for formal documents and traditional layouts.
- `DejaVuSerif.ttf` - Regular
- `DejaVuSerif-Bold.ttf` - Bold
- `DejaVuSerif-Italic.ttf` - Italic
- `DejaVuSerif-BoldItalic.ttf` - Bold Italic
### DejaVu Sans Mono (Monospace)
A fixed-width font perfect for code blocks and technical content.
- `DejaVuSansMono.ttf` - Regular
- `DejaVuSansMono-Bold.ttf` - Bold
- `DejaVuSansMono-Oblique.ttf` - Italic
- `DejaVuSansMono-BoldOblique.ttf` - Bold Italic
## Usage
### Easy Way: Using Font.from_family() (Recommended)
The easiest way to use bundled fonts is with the `Font.from_family()` class method:
```python
from pyWebLayout.style import Font, BundledFont, FontWeight, FontStyle
# Create a sans-serif font
sans_font = Font.from_family(
BundledFont.SANS,
font_size=16
)
# Create a bold serif font
serif_bold = Font.from_family(
BundledFont.SERIF,
font_size=18,
weight=FontWeight.BOLD
)
# Create an italic monospace font
mono_italic = Font.from_family(
BundledFont.MONOSPACE,
font_size=14,
style=FontStyle.ITALIC
)
# Create a bold italic sans font
sans_bold_italic = Font.from_family(
BundledFont.SANS,
font_size=16,
weight=FontWeight.BOLD,
style=FontStyle.ITALIC
)
```
### Manual Way: Using get_bundled_font_path()
You can also get the path to bundled fonts directly:
```python
from pyWebLayout.style import Font, BundledFont, FontWeight, FontStyle, get_bundled_font_path
# Get the path to a specific font
font_path = get_bundled_font_path(
BundledFont.SERIF,
weight=FontWeight.BOLD,
style=FontStyle.ITALIC
)
# Create a font with that path
font = Font(font_path=font_path, font_size=16)
```
### Low-level Way: Direct Paths
If you prefer to specify paths directly:
```python
import os
from pyWebLayout.style import Font, get_bundled_fonts_dir
# Get the fonts directory
fonts_dir = get_bundled_fonts_dir()
# Use specific font files
sans_font = Font(
font_path=os.path.join(fonts_dir, 'DejaVuSans.ttf'),
font_size=16
)
serif_bold = Font(
font_path=os.path.join(fonts_dir, 'DejaVuSerif-Bold.ttf'),
font_size=18
)
mono_italic = Font(
font_path=os.path.join(fonts_dir, 'DejaVuSansMono-Oblique.ttf'),
font_size=14
)
```
## License
The DejaVu fonts are free software under the terms of the Bitstream Vera Fonts Copyright and the Arev Fonts Copyright.
See `DEJAVU_LICENSE.txt` for full license details.
## About DejaVu Fonts
DejaVu fonts are a font family based on the Bitstream Vera Fonts. Its purpose is to provide a wider range of characters while maintaining the original look and feel through the process of collaborative development.
- **Version**: 2.37
- **Website**: https://dejavu-fonts.github.io/
- **Repository**: https://github.com/dejavu-fonts/dejavu-fonts
The fonts provide excellent Unicode coverage and are widely used in open-source projects.

View File

@ -4,7 +4,10 @@ Style system for the pyWebLayout library.
This module provides the core styling components used throughout the library. This module provides the core styling components used throughout the library.
""" """
from .fonts import Font, FontWeight, FontStyle, TextDecoration from .fonts import (
Font, FontWeight, FontStyle, TextDecoration,
BundledFont, get_bundled_font_path, get_bundled_fonts_dir
)
from .abstract_style import ( from .abstract_style import (
AbstractStyle, AbstractStyleRegistry, FontFamily, FontSize AbstractStyle, AbstractStyleRegistry, FontFamily, FontSize
) )
@ -14,6 +17,7 @@ from .alignment import Alignment
__all__ = [ __all__ = [
"Font", "FontWeight", "FontStyle", "TextDecoration", "Font", "FontWeight", "FontStyle", "TextDecoration",
"BundledFont", "get_bundled_font_path", "get_bundled_fonts_dir",
"AbstractStyle", "AbstractStyleRegistry", "FontFamily", "FontSize", "AbstractStyle", "AbstractStyleRegistry", "FontFamily", "FontSize",
"ConcreteStyle", "PageStyle", "Alignment" "ConcreteStyle", "PageStyle", "Alignment"
] ]

View File

@ -16,6 +16,9 @@ _FONT_CACHE: Dict[Tuple[Optional[str], int], ImageFont.FreeTypeFont] = {}
# Cache for bundled font path to avoid repeated filesystem lookups # Cache for bundled font path to avoid repeated filesystem lookups
_BUNDLED_FONT_PATH: Optional[str] = None _BUNDLED_FONT_PATH: Optional[str] = None
# Cache for bundled fonts directory
_BUNDLED_FONTS_DIR: Optional[str] = None
class FontWeight(Enum): class FontWeight(Enum):
NORMAL = "normal" NORMAL = "normal"
@ -33,6 +36,105 @@ class TextDecoration(Enum):
STRIKETHROUGH = "strikethrough" STRIKETHROUGH = "strikethrough"
class BundledFont(Enum):
"""Bundled font families available in pyWebLayout"""
SANS = "sans" # DejaVu Sans - modern sans-serif
SERIF = "serif" # DejaVu Serif - classic serif
MONOSPACE = "monospace" # DejaVu Sans Mono - fixed-width
def get_bundled_fonts_dir():
"""
Get the directory containing bundled fonts (cached).
Returns:
str: Path to the fonts directory, or None if not found
"""
global _BUNDLED_FONTS_DIR
# Return cached path if available
if _BUNDLED_FONTS_DIR is not None:
return _BUNDLED_FONTS_DIR
# First time - determine the path and cache it
current_dir = os.path.dirname(os.path.abspath(__file__))
fonts_dir = os.path.join(os.path.dirname(current_dir), 'assets', 'fonts')
if os.path.exists(fonts_dir) and os.path.isdir(fonts_dir):
_BUNDLED_FONTS_DIR = fonts_dir
logger.debug(f"Found bundled fonts directory at: {fonts_dir}")
return fonts_dir
else:
logger.warning(f"Bundled fonts directory not found at: {fonts_dir}")
_BUNDLED_FONTS_DIR = "" # Empty string to indicate "checked but not found"
return None
def get_bundled_font_path(
family: BundledFont = BundledFont.SANS,
weight: FontWeight = FontWeight.NORMAL,
style: FontStyle = FontStyle.NORMAL
) -> Optional[str]:
"""
Get the path to a specific bundled font file.
Args:
family: The font family (SANS, SERIF, or MONOSPACE)
weight: The font weight (NORMAL or BOLD)
style: The font style (NORMAL or ITALIC)
Returns:
str: Full path to the font file, or None if not found
Example:
>>> # Get bold italic sans font
>>> path = get_bundled_font_path(BundledFont.SANS, FontWeight.BOLD, FontStyle.ITALIC)
>>> font = Font(font_path=path, font_size=16)
"""
fonts_dir = get_bundled_fonts_dir()
if not fonts_dir:
return None
# Map font parameters to filename
family_map = {
BundledFont.SANS: "DejaVuSans",
BundledFont.SERIF: "DejaVuSerif",
BundledFont.MONOSPACE: "DejaVuSansMono"
}
base_name = family_map.get(family, "DejaVuSans")
# Build the font file name
parts = [base_name]
if weight == FontWeight.BOLD and style == FontStyle.ITALIC:
# Special case: both bold and italic
if family == BundledFont.MONOSPACE:
parts.append("BoldOblique")
elif family == BundledFont.SERIF:
parts.append("BoldItalic")
else: # SANS
parts.append("BoldOblique")
elif weight == FontWeight.BOLD:
parts.append("Bold")
elif style == FontStyle.ITALIC:
# Italic naming differs by family
if family == BundledFont.MONOSPACE or family == BundledFont.SANS:
parts.append("Oblique")
else: # SERIF
parts.append("Italic")
filename = "-".join(parts) + ".ttf"
font_path = os.path.join(fonts_dir, filename)
if os.path.exists(font_path):
logger.debug(f"Found bundled font: {filename}")
return font_path
else:
logger.warning(f"Bundled font not found: {filename}")
return None
class Font: class Font:
""" """
Font class to manage text rendering properties including font face, size, color, and styling. Font class to manage text rendering properties including font face, size, color, and styling.
@ -53,7 +155,7 @@ class Font:
Initialize a Font object with the specified properties. Initialize a Font object with the specified properties.
Args: Args:
font_path: Path to the font file (.ttf, .otf). If None, uses default font. font_path: Path to the font file (.ttf, .otf). If None, uses default bundled font.
font_size: Size of the font in points. font_size: Size of the font in points.
colour: RGB color tuple for the text. colour: RGB color tuple for the text.
weight: Font weight (normal or bold). weight: Font weight (normal or bold).
@ -76,6 +178,57 @@ class Font:
# Load the font file or use default # Load the font file or use default
self._load_font() self._load_font()
@classmethod
def from_family(cls,
family: BundledFont = BundledFont.SANS,
font_size: int = 16,
colour: Tuple[int, int, int] = (0, 0, 0),
weight: FontWeight = FontWeight.NORMAL,
style: FontStyle = FontStyle.NORMAL,
decoration: TextDecoration = TextDecoration.NONE,
background: Optional[Tuple[int, int, int, int]] = None,
language: str = "en_EN",
min_hyphenation_width: Optional[int] = None) -> 'Font':
"""
Create a Font using a bundled font family.
This is a convenient way to use the bundled DejaVu fonts without needing to
specify paths manually.
Args:
family: The font family to use (SANS, SERIF, or MONOSPACE)
font_size: Size of the font in points.
colour: RGB color tuple for the text.
weight: Font weight (normal or bold).
style: Font style (normal or italic).
decoration: Text decoration (none, underline, or strikethrough).
background: RGBA background color for the text. If None, transparent background.
language: Language code for hyphenation and text processing.
min_hyphenation_width: Minimum width in pixels required for hyphenation.
Returns:
Font object configured with the bundled font
Example:
>>> # Create a bold serif font
>>> font = Font.from_family(BundledFont.SERIF, font_size=18, weight=FontWeight.BOLD)
>>>
>>> # Create an italic monospace font
>>> code_font = Font.from_family(BundledFont.MONOSPACE, style=FontStyle.ITALIC)
"""
font_path = get_bundled_font_path(family, weight, style)
return cls(
font_path=font_path,
font_size=font_size,
colour=colour,
weight=weight,
style=style,
decoration=decoration,
background=background,
language=language,
min_hyphenation_width=min_hyphenation_width
)
def _get_bundled_font_path(self): def _get_bundled_font_path(self):
"""Get the path to the bundled font (cached)""" """Get the path to the bundled font (cached)"""
global _BUNDLED_FONT_PATH global _BUNDLED_FONT_PATH