Skip to content

Commit ce25399

Browse files
committed
docs: update API reference and JSON schema for gradient/image-filled text
- docs/api/text.md: add `fill` parameter to signature and params table, add `fill` to TextPart table, add "Gradient and image fills" examples section, add fill validation rules - docs/api/enums.md: add TextFillImage reference with params and examples - docs/api/index.md: add TextFillImage to public imports and pages table - docs/json-schema.md: add gradient-filled and image-filled text JSON examples with discriminator values documented https://claude.ai/code/session_01QK5iq4VqPsjWK8R9zJp1cg
1 parent 33b7866 commit ce25399

4 files changed

Lines changed: 142 additions & 1 deletion

File tree

docs/api/enums.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,3 +192,52 @@ canvas.background(
192192
),
193193
)
194194
```
195+
196+
---
197+
198+
## TextFillImage
199+
200+
An image used as a fill for text glyphs. The image is scaled to the text bounding box and masked to the glyph shapes.
201+
202+
```python
203+
from quickthumb import TextFillImage
204+
205+
TextFillImage(
206+
path="fire_texture.jpg",
207+
fit="cover",
208+
)
209+
```
210+
211+
| Parameter | Type | Default | Description |
212+
| --- | --- | --- | --- |
213+
| `path` | `str` | **required** | Local file path or remote URL for the fill image. |
214+
| `fit` | `str \| FitMode` | `"cover"` | How the image is scaled to the text bounding box. `"cover"`, `"contain"`, or `"fill"`. |
215+
216+
### Examples
217+
218+
```python
219+
from quickthumb import Canvas, TextFillImage
220+
221+
# Local file
222+
canvas.text(
223+
content="FIRE",
224+
size=140,
225+
fill=TextFillImage(path="assets/fire_texture.jpg", fit="cover"),
226+
position=("50%", "50%"),
227+
align="center",
228+
)
229+
230+
# Remote URL
231+
canvas.text(
232+
content="MARBLE",
233+
size=140,
234+
fill=TextFillImage(
235+
path="https://example.com/textures/marble.jpg",
236+
fit="cover",
237+
),
238+
position=("50%", "50%"),
239+
align="center",
240+
)
241+
```
242+
243+
Pass `TextFillImage` to the `fill` parameter of `.text()` or `TextPart`. See [Gradient and image fills](text.md#gradient-and-image-fills) for usage in context.

docs/api/index.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ from quickthumb import (
1717
RadialGradient,
1818
Shadow,
1919
Stroke,
20+
TextFillImage,
2021
TextPart,
2122
ValidationError,
2223
)
@@ -33,7 +34,7 @@ from quickthumb import (
3334
| [Shape](shape.md) | `.shape()` — rectangles and ellipses |
3435
| [Outline](outline.md) | `.outline()` — canvas border |
3536
| [Effects](effects.md) | `Stroke`, `Shadow`, `Glow`, `Filter`, `Background` |
36-
| [Enums & Gradients](enums.md) | `Align`, `BlendMode`, `FitMode`, `LinearGradient`, `RadialGradient` |
37+
| [Enums & Gradients](enums.md) | `Align`, `BlendMode`, `FitMode`, `LinearGradient`, `RadialGradient`, `TextFillImage` |
3738

3839
## Error types
3940

docs/api/text.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ canvas.text(
1010
font=None,
1111
size=None,
1212
color=None,
13+
fill=None,
1314
position=None,
1415
align=None,
1516
bold=False,
@@ -33,6 +34,7 @@ canvas.text(
3334
| `font` | `str \| None` | `None` | Font family name, local file path, or remote webfont URL. |
3435
| `size` | `int \| None` | `None` | Font size in pixels. Must be a positive integer. |
3536
| `color` | `str \| None` | `None` | Default text color. Hex string (`"#RRGGBB"` or `"#RRGGBBAA"`). |
37+
| `fill` | `LinearGradient \| RadialGradient \| TextFillImage \| None` | `None` | Gradient or image fill applied to the text glyphs. Takes visual precedence over `color` when set. See [Gradient and image fills](#gradient-and-image-fills). |
3638
| `position` | `tuple \| None` | `None` | `(x, y)` position. Values can be integers (px) or percentage strings (`"50%"`). |
3739
| `align` | `str \| Align \| tuple \| None` | `None` | Alignment of the text block. See [Align values](#align-values). |
3840
| `bold` | `bool` | `False` | Bold flag. Mutually exclusive with `weight`. |
@@ -151,6 +153,53 @@ canvas.text(
151153
!!! note "Webfont URLs"
152154
When `font` is a URL, `bold`, `italic`, and `weight` are ignored — the URL already points to a specific variant. Download separate URLs for bold/italic versions.
153155

156+
### Gradient and image fills
157+
158+
Fill text glyphs with a gradient or image instead of a flat color. Pass a `LinearGradient`, `RadialGradient`, or `TextFillImage` to `fill`.
159+
160+
```python
161+
from quickthumb import Canvas, LinearGradient, RadialGradient, TextFillImage, TextPart
162+
163+
# Linear gradient headline
164+
canvas.text(
165+
content="GRADIENT",
166+
size=120,
167+
fill=LinearGradient(angle=90, stops=[("#FF6B6B", 0.0), ("#4ECDC4", 1.0)]),
168+
position=("50%", "50%"),
169+
align="center",
170+
)
171+
172+
# Image-filled text
173+
canvas.text(
174+
content="TEXTURE",
175+
size=140,
176+
fill=TextFillImage(path="fire_texture.jpg", fit="cover"),
177+
position=("50%", "50%"),
178+
align="center",
179+
)
180+
181+
# Per-segment fills using TextPart
182+
canvas.text(
183+
content=[
184+
TextPart(
185+
text="HOT ",
186+
fill=LinearGradient(angle=45, stops=[("#FF4500", 0.0), ("#FFD700", 1.0)]),
187+
weight=900,
188+
),
189+
TextPart(
190+
text="COLD",
191+
fill=LinearGradient(angle=45, stops=[("#00BFFF", 0.0), ("#8A2BE2", 1.0)]),
192+
weight=900,
193+
),
194+
],
195+
size=110,
196+
position=("50%", "50%"),
197+
align="center",
198+
)
199+
```
200+
201+
`fill` on a `TextPart` overrides the layer-level `fill` for that segment only. `fill` and `color` are independent; when `fill` is set it takes visual precedence. See [TextFillImage](enums.md#textfillimage) for image fill options.
202+
154203
## TextPart
155204

156205
`TextPart` enables per-segment styling within a text layer.
@@ -161,6 +210,7 @@ from quickthumb import Stroke, TextPart
161210
TextPart(
162211
text="HOT",
163212
color="#FF3B30",
213+
fill=None,
164214
size=56,
165215
font="Impact",
166216
weight=900,
@@ -175,6 +225,7 @@ TextPart(
175225
| --- | --- | --- | --- |
176226
| `text` | `str` | **required** | The text segment. Cannot be empty. |
177227
| `color` | `str \| None` | `None` | Hex color override for this segment. |
228+
| `fill` | `LinearGradient \| RadialGradient \| TextFillImage \| None` | `None` | Gradient or image fill for this segment. Overrides the layer-level `fill` for this segment only. |
178229
| `size` | `int \| None` | `None` | Font size override for this segment. |
179230
| `font` | `str \| None` | `None` | Font override for this segment. |
180231
| `bold` | `bool \| None` | `None` | Bold override. Mutually exclusive with `weight`. |
@@ -192,3 +243,5 @@ TextPart(
192243
- `auto_scale=True` requires `max_width` to also be set.
193244
- `max_width` must be a positive integer or a positive percentage string like `"60%"`.
194245
- Percentage strings in `position` must match the pattern `-?N%` (negative percentages are valid).
246+
- `fill` and `color` are independent fields; `fill` takes visual precedence when both are set.
247+
- `TextFillImage.path` supports local file paths and remote URLs; missing local files raise `FileNotFoundError` at render time.

docs/json-schema.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,44 @@ Only include the fields you need — unspecified fields use their defaults.
132132
}
133133
```
134134

135+
**Gradient-filled text:**
136+
137+
```json
138+
{
139+
"type": "text",
140+
"content": "GRADIENT",
141+
"size": 120,
142+
"fill": {
143+
"type": "linear_gradient",
144+
"angle": 90,
145+
"stops": [["#FF6B6B", 0.0], ["#4ECDC4", 1.0]]
146+
},
147+
"position": ["50%", "50%"],
148+
"align": "center",
149+
"effects": []
150+
}
151+
```
152+
153+
**Image-filled text:**
154+
155+
```json
156+
{
157+
"type": "text",
158+
"content": "TEXTURE",
159+
"size": 140,
160+
"fill": {
161+
"type": "image",
162+
"path": "fire_texture.jpg",
163+
"fit": "cover"
164+
},
165+
"position": ["50%", "50%"],
166+
"align": "center",
167+
"effects": []
168+
}
169+
```
170+
171+
`fill` discriminator values: `"linear_gradient"`, `"radial_gradient"`, `"image"`. `fill` can also be set per `TextPart` entry using the same discriminated object.
172+
135173
**Align values:** `"center"`, `"left"`, `"right"`, `"top-left"`, `"top-center"`, `"top-right"`, `"bottom-left"`, `"bottom-center"`, `"bottom-right"`
136174

137175
---

0 commit comments

Comments
 (0)