Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
229 changes: 110 additions & 119 deletions buildconfig/stubs/pygame/surface.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -46,77 +46,72 @@ class Surface:
resolution and pixel format. Surfaces with 8-bit pixels use a color palette
to map to 24-bit color.

Call :meth:`pygame.Surface()` to create a new image object. The Surface will
be cleared to all black. The only required arguments are the sizes. With no
additional arguments, the Surface will be created in a format that best
matches the display Surface.

The pixel format can be controlled by passing the bit depth or an existing
Surface. The flags argument is a bitmask of additional features for the
surface. You can pass any combination of these flags:

::

HWSURFACE (obsolete in pygame 2) creates the image in video memory
SRCALPHA the pixel format will include a per-pixel alpha

Both flags are only a request, and may not be possible for all displays and
formats.

Advanced users can combine a set of bitmasks with a depth value. The masks
are a set of 4 integers representing which bits in a pixel will represent
each color. Normal Surfaces should not require the masks argument.

Surfaces can have many extra attributes like alpha planes, colorkeys, source
rectangle clipping. These functions mainly effect how the Surface is blitted
to other Surfaces. The blit routines will attempt to use hardware
acceleration when possible, otherwise they will use highly optimized
software blitting methods.

There are three types of transparency supported in pygame: colorkeys,
surface alphas, and pixel alphas. Surface alphas can be mixed with
colorkeys, but an image with per pixel alphas cannot use the other modes.
Colorkey transparency makes a single color value transparent. Any pixels
matching the colorkey will not be drawn. The surface alpha value is a single
value that changes the transparency for the entire image. A surface alpha of
255 is opaque, and a value of 0 is completely transparent.

Per pixel alphas are different because they store a transparency value for
every pixel. This allows for the most precise transparency effects, but it
also the slowest. Per pixel alphas cannot be mixed with surface alpha and
colorkeys.

There is support for pixel access for the Surfaces. Pixel access on hardware
surfaces is slow and not recommended. Pixels can be accessed using the
:meth:`get_at()` and :meth:`set_at()` functions. These methods are fine for
simple access, but will be considerably slow when doing of pixel work with
them. If you plan on doing a lot of pixel level work, it is recommended to
use a :class:`pygame.PixelArray`, which gives an array like view of the
surface. For involved mathematical manipulations try the
:mod:`pygame.surfarray` module (It's quite quick, but requires NumPy.)

Any functions that directly access a surface's pixel data will need that
surface to be lock()'ed. These functions can :meth:`lock()` and
:meth:`unlock()` the surfaces themselves without assistance. But, if a
function will be called many times, there will be a lot of overhead for
multiple locking and unlocking of the surface. It is best to lock the
surface manually before making the function call many times, and then
unlocking when you are finished. All functions that need a locked surface
will say so in their docs. Remember to leave the Surface locked only while
necessary.

Surface pixels are stored internally as a single number that has all the
colors encoded into it. Use the :meth:`map_rgb()` and
:meth:`unmap_rgb()` to convert between individual red, green, and blue
values into a packed integer for that Surface.

Surfaces can also reference sections of other Surfaces. These are created
with the :meth:`subsurface()` method. Any change to either Surface will
effect the other.

Each Surface contains a clipping area. By default the clip area covers the
entire Surface. If it is changed, all drawing operations will only effect
the smaller area.
When creating a new Surface it will be cleared to all black or all transparent
depending on the format. The only required argument is the size, a sequence
containing the width and height of the Surface. With no additional arguments
the format will best match the display Surface if one was initialized, otherwise
the most suitable format is chosen for the current platform.

One way to control the pixel format/characteristics is providing a bitmask of flags:
* ``SRCALPHA``: The Surface will include a per-pixel alpha channel (transparency).
* ``HWSURFACE``: (Obsolete in pygame 2) Creates the image in video memory.

Other exclusive ways to control the pixel format are available:
* Providing another ``Surface`` after the flags argument. That Surface's
format will be used and other arguments will be ignored.
* Advanced users can provide a bit depth and masks to precisely control how a
pixel's channels are organized in memory. If no masks are provided they will
be selected optimally from the bit depth. Normal usage of Surfaces is to leave
bit depth and masks as default.

An indexed format stores an index up to 255 instead of a color for each pixel,
therefore requires an associated palette. While pygame provides a default palette,
it can be controlled with the appropriate methods.

Surfaces additionally have alpha, colorkey and rectangle clipping. These characteristics
mainly affect how the Surface is blitted to other Surfaces. The blit routines will
attempt to use hardware acceleration when possible, otherwise they will use highly
optimized software blitting methods.
The clipping area is a rect defining the only area of the Surface that can be
modified. By default the whole Surface can be modified.

There are four types of transparency supported for a pygame Surface:
* Per-pixel alpha. Provided by a format with an alpha channel where
every pixel has its own alpha value.
* Pre-multiplied alpha: An advanced usage of per-pixel alpha. See
:meth:`Surface.premul_alpha` for more.
* Global alpha: A single alpha value that applies to the whole Surface.
* Colorkey: A color flagged to be considered transparent in operations.

Per-pixel alpha allows the greatest flexibility while being generally
slower than global alpha or colorkey. Pre-multiplied alpha is generally
faster than regular per-pixel alpha.

All types of transparency can be used togerher and correctly mix, except
pre-multipled alpha does not consider colorkey nor global alpha.
Also, An alpha of 255 is opaque while an alpha of 0 is fully transparent.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix capitalization error.

The word "An" should be lowercase "an" following a comma.

Apply this diff:

-    Also, An alpha of 255 is opaque while an alpha of 0 is fully transparent.
+    Also, an alpha of 255 is opaque while an alpha of 0 is fully transparent.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Also, An alpha of 255 is opaque while an alpha of 0 is fully transparent.
Also, an alpha of 255 is opaque while an alpha of 0 is fully transparent.
🤖 Prompt for AI Agents
In buildconfig/stubs/pygame/surface.pyi around line 92, fix the capitalization
after the comma: change "An alpha of 255 is opaque while an alpha of 0 is fully
transparent." to use a lowercase "an" following the comma so the sentence reads
"...an alpha of 255 is opaque while an alpha of 0 is fully transparent."; update
the line accordingly and run a quick lint/typo check.


Surfaces can be created that reference the pixel data of other Surfaces.
These are called subsurfaces and are created with the :meth:`subsurface()`
method. Changing the pixels referenced by either the original Surface or
the subsurface will have an effect on both.

You can use the :meth:`get_at()` and :meth:`set_at()` functions to access
pixels of Surfaces but while they are fine for simple access they will be
slow when doing pixel work with them.
It is advised to use a :class:`PixelArray` object to manipulate pixels efficiently.
Alternatively you can use the :mod:`pygame.surfarray` module (which requires NumPy).
Perform drawing operations and transformations on the pixels efficiently with the
:mod:`pygame.draw` and :mod:`pygame.transform` modules.
Additionally, the :meth:`map_rgb()` and :meth:`unmap_rgb()` methods are
available to convert between colors and their corresponding packed integers
(that is how each pixel is stored internally).

Any functions that directly access a Surface's pixel data will need that
Surface to be lock()'ed in some cases. Built in functions that manipulate
Surfaces will lock and unlock the Surface automatically. Only use manual
locking for a lot of sequential pixel modifications. This kind of locking
doesn't act like a mutex - it only prepares the Surface's pixels.
"""

@overload
Expand Down Expand Up @@ -291,43 +286,45 @@ class Surface:
@overload
def convert(self) -> Surface: ...
def convert(self, *args): # type: ignore
"""Change the pixel format of a surface.

Creates a new copy of the Surface with the pixel format changed. The new
pixel format can be determined from another existing Surface. Otherwise
depth, flags, and masks arguments can be used, similar to the
:meth:`pygame.Surface()` call.

If no arguments are passed the new Surface will have the same pixel
format as the display Surface. This is always the fastest format for
blitting. It is a good idea to convert all Surfaces before they are
blitted many times.

The converted Surface will have no pixel alphas. They will be stripped if
the original had them. See :meth:`convert_alpha()` for preserving or
creating per-pixel alphas.

The new copy will have the same class as the copied surface. This lets
a Surface subclass inherit this method without the need to override,
unless subclass specific instance attributes also need copying.
"""Change the pixel format of a Surface.

Creates a new copy of the Surface with the pixel format changed. The
format can be controlled in different ways:
* If no arguments are passed the new Surface will have the same pixel
format as the display Surface which is always the fastest format
for blitting. It is a good idea to convert all Surfaces before
blitting them. In this case the converted Surface won't have any
alpha. See :meth:`convert_alpha()` for preserving or creating per-pixel alpha.
A :class:`pygame.error` exception is thrown if the display Surface
was not initialized.
Comment on lines +298 to +299
Copy link
Contributor

@coderabbitai coderabbitai bot Oct 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use Python exception terminology.

Python exceptions are "raised" rather than "thrown". This ensures consistency with standard Python documentation conventions.

Apply this diff:

-             A :class:`pygame.error` exception is thrown if the display Surface
-             was not initialized.
+             A :class:`pygame.error` exception is raised if the display Surface
+             was not initialized.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
A :class:`pygame.error` exception is thrown if the display Surface
was not initialized.
A :class:`pygame.error` exception is raised if the display Surface
was not initialized.
🤖 Prompt for AI Agents
In buildconfig/stubs/pygame/surface.pyi around lines 298 to 299, the docstring
uses the term "thrown" for exceptions; replace it with Python terminology
"raised" so the sentence reads that "A :class:`pygame.error` exception is raised
if the display Surface was not initialized." Update the line accordingly to
maintain consistency with Python docs.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're AI can you not notice this improvements one at a time so I don't spam commits 🙏

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for other instances of "thrown" in the surface.pyi file
rg -n "thrown" buildconfig/stubs/pygame/surface.pyi

Length of output: 83


@damusss, I understand! I've checked the entire file and this is actually the only instance of "thrown" vs "raised", so there's nothing else to batch with it for now.

For future reviews, I'll note to look for patterns across the entire PR and batch similar improvements together to minimize commits. 👍


🧬 Code Graph Analysis Results

[No. of relevant snippets: 4]

buildconfig/stubs/pygame/mixer.pyi, lines 76-76
def copy(self) -> Self: ...

buildconfig/stubs/pygame/cursors.pyi, lines 83-83
def copy(self) -> Cursor: ...

buildconfig/stubs/pygame/mask.pyi, lines 21-21
def copy(self) -> Mask: ...

buildconfig/stubs/pygame/pixelarray.pyi, lines 19-19
def surface(self) -> Surface: ...


✏️ Learnings added
Learnt from: damusss
PR: pygame-community/pygame-ce#3604
File: buildconfig/stubs/pygame/surface.pyi:298-299
Timestamp: 2025-10-11T10:24:52.698Z
Learning: For the pygame-community/pygame-ce repository, batch similar documentation or terminology improvements together in a single comment rather than pointing them out individually. This helps avoid unnecessary commit spam.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

* If another Surface is provided, the format of that Surface will
be used.
* Passing the bit depth of a pixel that will result in the same formats
explained in the :class:`Surface` constructor. Flags can also be
provided, for example ``SRCALPHA`` will request an alpha channel.
* Passing the bitmasks of the pixels and flags. Note that the bit depth
could be calculated wrong, therefore it is not advised to use this
path as it might be deprecated in the future.

The returned surface will have the same class as this surface, making this
method safe for subclasses. The colorkey and the palette for indexed Surfaces
are also preserved if they were present.

.. versionchanged:: 2.5.0 converting to a known format will succeed without
a window/display surface.
a window/display Surface.
"""

def convert_alpha(self) -> Surface:
"""Change the pixel format of a surface including per pixel alphas.
"""Change the pixel format of a Surface including per pixel alphas.

Creates a new copy of the surface with the desired pixel format. The new
surface will be in a format suited for quick blitting to the display surface
with per pixel alpha.
Creates a new copy of the Surface with the desired pixel format that contains
an alpha channel. Unlike the :meth:`convert()` method, the pixel format
for the new Surface will not be exactly the same as the display Surface,
but it will be suited and optimized for fast alpha blitting to it.

Unlike the :meth:`convert()` method, the pixel format for the new
surface will not be exactly the same as the display surface, but it will
be optimized for fast alpha blitting to it.

As with :meth:`convert()` the returned surface has the same class as
the converted surface.
As with :meth:`convert()`, the returned Surface has the same class as this
Surface. A :class:`pygame.error` exception will be raised if the display
Surface has not been initialized yet.

.. versionchanged:: 2.4.0 'Surface' argument deprecated.
"""
Expand Down Expand Up @@ -797,28 +794,22 @@ class Surface:
flags bitmask. Typical flags are ``RLEACCEL``, ``SRCALPHA``, and
``SRCCOLORKEY``.

Here is a more complete list of flags. A full list can be found in
``SDL_video.h``

::

SWSURFACE 0x00000000 # Surface is in system memory
HWSURFACE 0x00000001 # (obsolete in pygame 2) Surface is in video memory
ASYNCBLIT 0x00000004 # (obsolete in pygame 2) Use asynchronous blits if possible
Here is a more complete list of flags:
* ``SRCALPHA``: Blit uses source alpha blending
* ``SWSURFACE``: Surface is in system memory
* ``HWACCEL``: Blit uses hardware acceleration
* ``SRCCOLORKEY``: Blit uses a source color key
* ``RLEACCELOK``: Private flag
* ``RLEACCEL``: Surface has run-length encoding
* ``PREALLOC``: Surface uses preallocated memory

See :func:`pygame.display.set_mode()` for flags exclusive to the
display surface.

Used internally (read-only)
display Surface.

::
Obsolete flags:

HWACCEL 0x00000100 # Blit uses hardware acceleration
SRCCOLORKEY 0x00001000 # Blit uses a source color key
RLEACCELOK 0x00002000 # Private flag
RLEACCEL 0x00004000 # Surface is RLE encoded
SRCALPHA 0x00010000 # Blit uses source alpha blending
PREALLOC 0x01000000 # Surface uses preallocated memory
* ``HWSURFACE``: (obsolete in pygame 2) Surface is in video memory
* ``ASYNCBLIT``: (obsolete in pygame 2) Use asynchronous blits if possible
"""

def get_pitch(self) -> int:
Expand Down
Loading