Beispiel #1
0
/**
 * \brief Sets the opacity of this surface.
 * \param opacity The opacity (0 to 255).
 */
void Surface::set_opacity(uint8_t opacity) {

  this->opacity = opacity;

  if (software_destination  // The destination surface is in RAM.
      || !Video::is_acceleration_enabled()  // The rendering is in RAM.
  ) {
    if (internal_surface == nullptr) {
      create_software_surface();
    }

    int error = SDL_SetSurfaceAlphaMod(internal_surface.get(), opacity);
    if (error != 0) {
      Debug::error(SDL_GetError());
    }
    is_rendered = false;  // The surface has changed.
  }

  // If this is a hardware surface, the opacity is applied later.
}
Beispiel #2
0
/**
 * \brief Sets the opacity of this surface.
 * \param opacity the opacity (0 to 255).
 */
void Surface::set_opacity(uint8_t opacity) {

  if (software_destination  // The destination surface is in RAM.
      || !Video::is_acceleration_enabled()  // The rendering is in RAM.
  ) {
    if (internal_surface == NULL) {
      create_software_surface();
    }

    // The surface must be 32-bit with alpha value for this function to work.
    convert_software_surface();

    int error = SDL_SetSurfaceAlphaMod(internal_surface, opacity);
    if (error != 0) {
      Debug::error(SDL_GetError());
    }
    is_rendered = false;  // The surface has changed.
  }
  else {
    internal_opacity = opacity;
  }
}
Beispiel #3
0
/**
 * \brief Draws a subrectangle of this surface on another surface.
 * \param region The subrectangle to draw in this object.
 * \param dst_surface The destination surface.
 * \param dst_position Coordinates on the destination surface.
 */
void Surface::raw_draw_region(
    const Rectangle& region,
    Surface& dst_surface,
    const Point& dst_position) {

  if (dst_surface.software_destination  // The destination surface is in RAM.
      || !Video::is_acceleration_enabled()  // The rendering is in RAM.
  ) {

    if (dst_surface.internal_surface == nullptr) {
      dst_surface.create_software_surface();
    }

    // First, draw subsurfaces if any.
    // They can exist if the video mode recently switched from an accelerated
    // one to a software one.
    if (!subsurfaces.empty()) {

      if (this->internal_surface == nullptr) {
        create_software_surface();
      }

      std::vector<SubSurfaceNodePtr> subsurfaces = this->subsurfaces;
      this->subsurfaces.clear();  // Avoid infinite recursive calls if there are cycles.

      for (SubSurfaceNodePtr& subsurface: subsurfaces) {

        // TODO draw the subsurfaces of the whole tree recursively instead.
        // The current version is not correct because it handles only one level
        // (it ignores subsurface->subsurfaces).
        // Plus it needs the workaround above to avoid a stack overflow.
        subsurface->src_surface->raw_draw_region(
            subsurface->src_rect,
            *this,
            subsurface->dst_rect.get_xy()
        );
        subsurface = nullptr;
      }
      clear_subsurfaces();
    }

    if (this->internal_surface != nullptr) {
      // The source surface is not empty: draw it onto the destination.

      SDL_SetSurfaceBlendMode(
            this->internal_surface.get(),
            get_sdl_blend_mode()
      );
      SDL_BlitSurface(
          this->internal_surface.get(),
          region.get_internal_rect(),
          dst_surface.internal_surface.get(),
          Rectangle(dst_position).get_internal_rect()
      );
    }
    else if (internal_color != nullptr) { // No internal surface to draw: this may be a color.

      if (get_blend_mode() == BlendMode::BLEND && internal_color->get_alpha() == 255) {
        // Fill with opaque color: we can directly modify the destination pixels.
        Rectangle dst_rect(
            dst_position,
            region.get_size()
        );
        SDL_FillRect(
            dst_surface.internal_surface.get(),
            dst_rect.get_internal_rect(),
            get_color_value(*internal_color)
        );
      }
      else {
        // Fill with semi-transparent pixels: perform alpha-blending.
        create_software_surface();
        SDL_FillRect(
            this->internal_surface.get(),
            nullptr,
            get_color_value(*internal_color)
        );
        SDL_BlitSurface(
            this->internal_surface.get(),
            region.get_internal_rect(),
            dst_surface.internal_surface.get(),
            Rectangle(dst_position).get_internal_rect()
        );
      }
    }
  }
  else {
    // The destination is a GPU surface (a texture).
    // Do not draw anything, just store the operation in the tree instead.
    // The actual drawing will be done at rendering time in GPU.

    SurfacePtr src_surface = std::static_pointer_cast<Surface>(shared_from_this());
    dst_surface.add_subsurface(src_surface, region, dst_position);
  }

  dst_surface.is_rendered = false;
}
Beispiel #4
0
/**
 * \brief Draws a subrectangle of this surface on another surface.
 * \param region The subrectangle to draw in this object.
 * \param dst_surface The destination surface.
 * \param dst_position Coordinates on the destination surface.
 * The width and height of this rectangle are ignored.
 */
void Surface::raw_draw_region(
    const Rectangle& region,
    Surface& dst_surface,
    const Rectangle& dst_position) {

  if (dst_surface.software_destination  // The destination surface is in RAM.
      || !Video::is_acceleration_enabled()  // The rendering is in RAM.
  ) {

    if (dst_surface.internal_surface == NULL) {
      dst_surface.create_software_surface();
    }

    // First, draw subsurfaces if any.
    // They can exist if the video mode recently switched from an accelerated
    // one to a software one.
    if (!subsurfaces.empty()) {

      if (this->internal_surface == NULL) {
        create_software_surface();
      }

      std::vector<SubSurfaceNode*> subsurfaces = this->subsurfaces;
      this->subsurfaces.clear();  // Avoid infinite recursive calls if there are cycles.

      std::vector<SubSurfaceNode*>::const_iterator it;
      const std::vector<SubSurfaceNode*>::const_iterator end = subsurfaces.end();
      for (it = subsurfaces.begin(); it != end; ++it) {
        SubSurfaceNode* subsurface = *it;

        // TODO draw the subsurfaces of the whole tree recursively instead.
        // The current version is not correct because it handles only one level
        // (it ignores subsurface->subsurfaces).
        // Plus it needs the workaround above to avoid a stack overflow.
        subsurface->src_surface->raw_draw_region(
            subsurface->src_rect,
            *this,
            subsurface->dst_rect
        );
        RefCountable::unref(subsurface);
      }
      clear_subsurfaces();
    }

    if (this->internal_surface != NULL) {
      // The source surface is not empty: draw it onto the destination.

      SDL_BlitSurface(
          this->internal_surface,
          region.get_internal_rect(),
          dst_surface.internal_surface,
          Rectangle(dst_position).get_internal_rect()
      );
    }
    else if (internal_color != NULL) { // No internal surface to draw: this may be a color.

      if (internal_color->get_internal_color()->a == 255) {
        // Fill with opaque color: we can directly modify the destination pixels.
        Rectangle dst_rect(
            dst_position.get_x(), dst_position.get_y(),
            region.get_width(), region.get_height()
        );
        SDL_FillRect(
            dst_surface.internal_surface,
            dst_rect.get_internal_rect(),
            this->internal_color->get_internal_value()
        );
      }
      else {
        // Fill with semi-transparent pixels: perform alpha-blending.
        create_software_surface();
        SDL_FillRect(
            this->internal_surface,
            NULL,
            this->internal_color->get_internal_value()
        );
        SDL_BlitSurface(
            this->internal_surface,
            region.get_internal_rect(),
            dst_surface.internal_surface,
            Rectangle(dst_position).get_internal_rect()
        );
      }
    }
  }
  else {
    // The destination is a GPU surface (a texture).
    // Do not draw anything, just store the operation in the tree instead.
    // The actual drawing will be done at rendering time in GPU.
    dst_surface.add_subsurface(*this, region, dst_position);
  }

  dst_surface.is_rendered = false;
}