Skip to content

Commit d20866c

Browse files
committed
Clarify FreeText annotation color options
1 parent cd55ccf commit d20866c

File tree

3 files changed

+26
-15
lines changed

3 files changed

+26
-15
lines changed

docs/annot.rst

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -170,8 +170,7 @@ There is a parent-child relationship between an annotation and its page. If the
170170

171171
.. note::
172172

173-
* While 'FreeText', 'Line', 'PolyLine', and 'Polygon' annotations can have these properties, (Py-) MuPDF does not support line ends for 'FreeText', because the call-out variant of it is not supported.
174-
* *(Changed in v1.16.16)* Some symbols have an interior area (diamonds, circles, squares, etc.). By default, these areas are filled with the fill color of the annotation. If this is *None*, then white is chosen. The *fill_color* argument of :meth:`Annot.update` can now be used to override this and give line end symbols their own fill color.
173+
* Some symbols have an interior area (diamonds, circles, squares, etc.). These areas are filled with the fill color or the stroke color, depending on the annotation type.
175174

176175
:arg int start: The symbol number for the first point.
177176
:arg int end: The symbol number for the last point.
@@ -305,15 +304,13 @@ There is a parent-child relationship between an annotation and its page. If the
305304

306305
.. method:: set_colors(colors=None, stroke=None, fill=None)
307306

308-
* Changed in version 1.16.9: Allow colors to be directly set. These parameters are used if *colors* is not a dictionary.
309-
310-
Changes the "stroke" and "fill" colors for supported annotation types -- not all annotations accept both.
307+
Changes the "stroke" and "fill" colors for supported annotation types -- not all annotation types accept both. **Do not use this method at all for FreeText annotations** because it has its special conventions to deal with up to three colors (border, fill, text).
311308

312309
:arg dict colors: a dictionary containing color specifications. For accepted dictionary keys and values see below. The most practical way should be to first make a copy of the *colors* property and then modify this dictionary as required.
313310
:arg sequence stroke: see above.
314311
:arg sequence fill: see above.
315312

316-
*Changed in v1.18.5:* To completely remove a color specification, use an empty sequence like `[]`. If you specify `None`, an existing specification will not be changed.
313+
To completely remove a color specification, use an empty sequence like `[]`. If you specify `None`, an existing specification will not be changed.
317314

318315

319316
.. method:: delete_responses()
@@ -349,20 +346,26 @@ There is a parent-child relationship between an annotation and its page. If the
349346
Color specifications may be made in the usual format used in PuMuPDF as sequences of floats ranging from 0.0 to 1.0 (including both). The sequence length must be 1, 3 or 4 (supporting GRAY, RGB and CMYK colorspaces respectively). For GRAY, just a float is also acceptable.
350347

351348
:arg float opacity: *(new in v1.16.14)* **valid for all annotation types:** change or set the annotation's transparency. Valid values are *0 <= opacity < 1*.
349+
352350
:arg str blend_mode: *(new in v1.16.14)* **valid for all annotation types:** change or set the annotation's blend mode. For valid values see :ref:`BlendModes`.
351+
353352
:arg float fontsize: change :data:`fontsize` of the text. 'FreeText' annotations only.
354-
:arg sequence,float text_color: change the text color. 'FreeText' annotations only.
355-
:arg sequence,float border_color: change the border color. 'FreeText' annotations only.
356-
:arg sequence,float fill_color: the fill color.
357353

358-
* 'Line', 'Polyline', 'Polygon' annotations: use it to give applicable line end symbols a fill color other than that of the annotation *(changed in v1.16.16)*.
354+
:arg sequence,float text_color: change the text color. 'FreeText' annotations only. This has the same effect as ``border_color``. Note that the text color of rich-text annotations cannot be changed at all because it is set by HTML / CSS syntax and part of the text itself.
355+
356+
:arg sequence,float border_color: change the border color. 'FreeText' annotations only. This has the same effect as ``text_color``.
357+
358+
:arg sequence,float fill_color: the fill color.
359359

360360
:arg bool cross_out: *(new in v1.17.2)* add two diagonal lines to the annotation rectangle. 'Redact' annotations only. If not desired, *False* must be specified even if the annotation was created with *False*.
361+
361362
:arg int rotate: new rotation value. Default (-1) means no change. Supports 'FreeText' and several other annotation types (see :meth:`Annot.set_rotation`), [#f1]_. Only choose 0, 90, 180, or 270 degrees for 'FreeText'. Otherwise any integer is acceptable.
362363

363364
:rtype: bool
364365

365-
.. note:: Using this method inside a :meth:`Page.annots` loop is **not recommended!** This is because most annotation updates require the owning page to be reloaded -- which cannot be done inside this loop. Please use the example coding pattern given in the documentation of this generator.
366+
This method is the only way to change the colors of a FreeText annotation. You cannot use `:meth:Annot.set_colors` for this purpose. But be aware that for rich-text annotations, the text color is never changed. The text color is set by the *text_color* entry of the *info* dictionary. This is a limitation of MuPDF and not a bug.
367+
368+
.. caution:: Using this method inside a :meth:`Page.annots` loop is **not recommended!** This is because most annotation updates require the owning page to be reloaded -- which cannot be done inside this loop. Please use the example coding pattern given in the documentation of this generator.
366369

367370

368371
.. attribute:: file_info
@@ -500,7 +503,10 @@ There is a parent-child relationship between an annotation and its page. If the
500503

501504
.. attribute:: colors
502505

503-
dictionary of two lists of floats in range *0 <= float <= 1* specifying the "stroke" and the interior ("fill") colors. The stroke color is used for borders and everything that is actively painted or written ("stroked"). The fill color is used for the interior of objects like line ends, circles and squares. The lengths of these lists implicitly determine the colorspaces used: 1 = GRAY, 3 = RGB, 4 = CMYK. So "[1.0, 0.0, 0.0]" stands for RGB color red. Both lists can be empty if no color is specified.
506+
dictionary of two lists of floats in range *0 <= float <= 1* specifying the "stroke" and the interior ("fill") colors. The stroke color is used for borders and everything that is actively painted or written ("stroked"). The fill color is used for the interior of objects like line ends, circles and squares. The lengths of these lists implicitly determine the colorspaces used: 1 = GRAY, 3 = RGB, 4 = CMYK. So "[1.0, 0.0, 0.0]" stands for RGB color red. Both lists can be empty if no color is specified. Be aware about some potentially unexpected cases:
507+
508+
* The color of Highlight annotations is a **stroke** color, contrary to intuition.
509+
* The color if FreeText annotations is a **stroke** color, but appears as the color that fills the rectangle and any applicable line end symbols. Text color and border color cannot be accessed at all.
504510

505511
:rtype: dict
506512

docs/page.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -216,9 +216,9 @@ In a nutshell, this is what you can do with PyMuPDF:
216216

217217
:arg list,tuple,float fill_color: the fill color. This is used for ``rect`` and the end point of the callout lines when applicable. Default is ``None``.
218218

219-
:arg list,tuple,float border_color: This parameter only has an effect if `richtext=True`. Otherwise, ``text_color`` is used.
219+
:arg list,tuple,float border_color: This parameter **only has an effect** if `richtext=True`. Otherwise, ``text_color`` is used.
220220

221-
:arg float border_width: the width of border and ``callout`` lines. Default is 0 (no border), in which case callout lines may still appear with some hairline width, depending on the PDF viewer used.
221+
:arg float border_width: the width of border and ``callout`` lines. Default is 0 (no border), in which case callout lines may still appear with some hairline width, depending on the PDF viewer used. In any case, this value must be positive to see a border line.
222222

223223
:arg list,tuple dashes: a list of floats specifying how border and callout lines should be dashed. Default is ``None``.
224224

@@ -232,7 +232,7 @@ In a nutshell, this is what you can do with PyMuPDF:
232232

233233
:arg int rotate: the text orientation. Accepted values are integer multiples of 90°. Invalid entries receive a rotation of 0.
234234

235-
:arg bool richtext: treat ``text`` as HTML syntax. This allows to achieve **bold**, *italic*, arbitrary text colors, font sizes, text alignment including justify and more - as far as HTML and styling instructions support this. This is similar to what happens in :meth:`Page.insert_htmlbox`. The base library will for example pull in required fonts if it encounters characters not contained in the standard ones. Some parameters are ignored if this option is set, as mentioned above. Default is ``False``.
235+
:arg bool richtext: treat ``text`` as HTML syntax. This allows to achieve **bold**, *italic*, arbitrary text colors, font sizes, text alignment including justify and more - as far as the PDF subset of HTML and styling instructions supports this. This is similar to what happens in :meth:`Page.insert_htmlbox`. The base library will for example pull in required fonts if it encounters characters not contained in the standard ones. Some parameters are ignored if this option is set, as mentioned above. Default is ``False``.
236236

237237
:arg str style: supply optional HTML styling information in CSS syntax. Ignored if `richtext=False`.
238238

src/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,14 +1326,19 @@ def set_colors(self, colors=None, stroke=None, fill=None):
13261326

13271327
Use either a dict or the direct arguments.
13281328
"""
1329+
if self.type[0] == mupdf.PDF_ANNOT_FREE_TEXT:
1330+
raise ValueError("cannot be used for FreeText annotations")
1331+
13291332
CheckParent(self)
13301333
doc = self.get_parent().parent
13311334
if type(colors) is not dict:
13321335
colors = {"fill": fill, "stroke": stroke}
13331336
fill = colors.get("fill")
13341337
stroke = colors.get("stroke")
1338+
13351339
fill_annots = (mupdf.PDF_ANNOT_CIRCLE, mupdf.PDF_ANNOT_SQUARE, mupdf.PDF_ANNOT_LINE, mupdf.PDF_ANNOT_POLY_LINE, mupdf.PDF_ANNOT_POLYGON,
13361340
mupdf.PDF_ANNOT_REDACT,)
1341+
13371342
if stroke in ([], ()):
13381343
doc.xref_set_key(self.xref, "C", "[]")
13391344
elif stroke is not None:

0 commit comments

Comments
 (0)