| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- /*
- * This source file is part of libRocket, the HTML/CSS Interface Middleware
- *
- * For the latest information, see http://www.librocket.com
- *
- * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- */
- #include "precompiled.h"
- #include "ElementImage.h"
- #include "../../Include/Rocket/Core.h"
- #include "TextureDatabase.h"
- #include "TextureResource.h"
- namespace Rocket {
- namespace Core {
- // Constructs a new ElementImage.
- ElementImage::ElementImage(const String& tag) : Element(tag), dimensions(-1, -1), geometry(this)
- {
- ResetCoords();
- geometry_dirty = false;
- texture_dirty = true;
- }
- ElementImage::~ElementImage()
- {
- }
- // Sizes the box to the element's inherent size.
- bool ElementImage::GetIntrinsicDimensions(Vector2f& _dimensions)
- {
- // Check if we need to reload the texture.
- if (texture_dirty)
- LoadTexture();
- // Calculate the x dimension.
- if (HasAttribute("width"))
- dimensions.x = GetAttribute< float >("width", -1);
- else if (using_coords)
- dimensions.x = (float) (coords[2] - coords[0]);
- else
- dimensions.x = (float) texture.GetDimensions(GetRenderInterface()).x;
- // Calculate the y dimension.
- if (HasAttribute("height"))
- dimensions.y = GetAttribute< float >("height", -1);
- else if (using_coords)
- dimensions.y = (float) (coords[3] - coords[1]);
- else
- dimensions.y = (float) texture.GetDimensions(GetRenderInterface()).y;
- // Return the calculated dimensions. If this changes the size of the element, it will result in
- // a 'resize' event which is caught below and will regenerate the geometry.
- _dimensions = dimensions;
- return true;
- }
- // Renders the element.
- void ElementImage::OnRender()
- {
- // Regenerate the geometry if required (this will be set if 'coords' changes but does not
- // result in a resize).
- if (geometry_dirty)
- GenerateGeometry();
- // Render the geometry beginning at this element's content region.
- geometry.Render(GetAbsoluteOffset(Rocket::Core::Box::CONTENT).Round());
- }
- // Called when attributes on the element are changed.
- void ElementImage::OnAttributeChange(const Rocket::Core::AttributeNameList& changed_attributes)
- {
- // Call through to the base element's OnAttributeChange().
- Rocket::Core::Element::OnAttributeChange(changed_attributes);
- float dirty_layout = false;
- // Check for a changed 'src' attribute. If this changes, the old texture handle is released,
- // forcing a reload when the layout is regenerated.
- if (changed_attributes.find("src") != changed_attributes.end())
- {
- texture_dirty = true;
- dirty_layout = true;
- }
- // Check for a changed 'width' attribute. If this changes, a layout is forced which will
- // recalculate the dimensions.
- if (changed_attributes.find("width") != changed_attributes.end() ||
- changed_attributes.find("height") != changed_attributes.end())
- {
- dirty_layout = true;
- }
- // Check for a change to the 'coords' attribute. If this changes, the coordinates are
- // recomputed and a layout forced.
- if (changed_attributes.find("coords") != changed_attributes.end())
- {
- if (HasAttribute("coords"))
- {
- StringList coords_list;
- StringUtilities::ExpandString(coords_list, GetAttribute< String >("coords", ""));
- if (coords_list.size() != 4)
- {
- Rocket::Core::Log::Message(Log::LT_WARNING, "Element '%s' has an invalid 'coords' attribute; coords requires 4 values, found %d.", GetAddress().CString(), coords_list.size());
- ResetCoords();
- }
- else
- {
- for (size_t i = 0; i < 4; ++i)
- coords[i] = atoi(coords_list[i].CString());
- // Check for the validity of the coordinates.
- if (coords[0] < 0 || coords[2] < coords[0] ||
- coords[1] < 0 || coords[3] < coords[1])
- {
- Rocket::Core::Log::Message(Log::LT_WARNING, "Element '%s' has an invalid 'coords' attribute; invalid coordinate values specified.", GetAddress().CString());
- ResetCoords();
- }
- else
- {
- // We have new, valid coordinates; force the geometry to be regenerated.
- geometry_dirty = true;
- using_coords = true;
- }
- }
- }
- else
- ResetCoords();
- // Coordinates have changes; this will most likely result in a size change, so we need to force a layout.
- dirty_layout = true;
- }
- if (dirty_layout)
- DirtyLayout();
- }
- void ElementImage::OnPropertyChange(const PropertyNameList& changed_properties)
- {
- Element::OnPropertyChange(changed_properties);
- if (changed_properties.find(IMAGE_COLOR) != changed_properties.end() ||
- changed_properties.find(OPACITY) != changed_properties.end()) {
- GenerateGeometry();
- }
- }
- // Regenerates the element's geometry.
- void ElementImage::ProcessEvent(Rocket::Core::Event& event)
- {
- Element::ProcessEvent(event);
- if (event.GetTargetElement() == this &&
- event == RESIZE)
- {
- GenerateGeometry();
- }
- }
- void ElementImage::GenerateGeometry()
- {
- // Release the old geometry before specifying the new vertices.
- geometry.Release(true);
- std::vector< Rocket::Core::Vertex >& vertices = geometry.GetVertices();
- std::vector< int >& indices = geometry.GetIndices();
- vertices.resize(4);
- indices.resize(6);
- // Generate the texture coordinates.
- Vector2f texcoords[2];
- if (using_coords)
- {
- Vector2f texture_dimensions((float) texture.GetDimensions(GetRenderInterface()).x, (float) texture.GetDimensions(GetRenderInterface()).y);
- if (texture_dimensions.x == 0)
- texture_dimensions.x = 1;
- if (texture_dimensions.y == 0)
- texture_dimensions.y = 1;
- texcoords[0].x = (float) coords[0] / texture_dimensions.x;
- texcoords[0].y = (float) coords[1] / texture_dimensions.y;
- texcoords[1].x = (float) coords[2] / texture_dimensions.x;
- texcoords[1].y = (float) coords[3] / texture_dimensions.y;
- }
- else
- {
- texcoords[0] = Vector2f(0, 0);
- texcoords[1] = Vector2f(1, 1);
- }
- float opacity = GetProperty<float>(OPACITY);
- Colourb quad_colour = GetProperty<Colourb>(IMAGE_COLOR);
- quad_colour.alpha = (byte)(opacity * (float)quad_colour.alpha);
-
- Vector2f quad_size = GetBox().GetSize(Rocket::Core::Box::CONTENT).Round();
- Rocket::Core::GeometryUtilities::GenerateQuad(&vertices[0], &indices[0], Vector2f(0, 0), quad_size, quad_colour, texcoords[0], texcoords[1]);
- geometry_dirty = false;
- }
- bool ElementImage::LoadTexture()
- {
- texture_dirty = false;
- // Get the source URL for the image.
- String image_source = GetAttribute< String >("src", "");
- if (image_source.Empty())
- return false;
- geometry_dirty = true;
- Rocket::Core::ElementDocument* document = GetOwnerDocument();
- URL source_url(document == NULL ? "" : document->GetSourceURL());
- if (!texture.Load(image_source, source_url.GetPath()))
- {
- geometry.SetTexture(NULL);
- return false;
- }
- // Set the texture onto our geometry object.
- geometry.SetTexture(&texture);
- return true;
- }
- void ElementImage::ResetCoords()
- {
- using_coords = false;
- for (int i = 0; i < 4; ++i)
- coords[i] = -1;
- }
- }
- }
|