2 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include "npatch-visual.h"
22 #include <dali/devel-api/adaptor-framework/image-loading.h>
23 #include <dali/devel-api/rendering/renderer-devel.h>
24 #include <dali/integration-api/debug.h>
27 #include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
28 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
29 #include <dali-toolkit/internal/visuals/image-visual-shader-factory.h>
30 #include <dali-toolkit/internal/visuals/npatch-loader.h>
31 #include <dali-toolkit/internal/visuals/rendering-addon.h>
32 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
33 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
34 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
35 #include <dali-toolkit/internal/visuals/visual-factory-impl.h>
36 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
37 #include <dali-toolkit/public-api/visuals/visual-properties.h>
48 * @brief Creates the geometry formed from the vertices and indices
50 * @param[in] vertices The vertices to generate the geometry from
51 * @param[in] indices The indices to generate the geometry from
52 * @return The geometry formed from the vertices and indices
54 Geometry GenerateGeometry(const Vector<Vector2>& vertices, const Vector<unsigned short>& indices)
56 Property::Map vertexFormat;
57 vertexFormat["aPosition"] = Property::VECTOR2;
58 VertexBuffer vertexBuffer = VertexBuffer::New(vertexFormat);
59 if(vertices.Size() > 0)
61 vertexBuffer.SetData(&vertices[0], vertices.Size());
64 // Create the geometry object
65 Geometry geometry = Geometry::New();
66 geometry.AddVertexBuffer(vertexBuffer);
67 if(indices.Size() > 0)
69 geometry.SetIndexBuffer(&indices[0], indices.Size());
76 * @brief Adds the indices to form a quad composed off two triangles where the indices are organised in a grid
78 * @param[out] indices The indices to add to
79 * @param[in] rowIdx The row index to start the quad
80 * @param[in] nextRowIdx The index to the next row
82 void AddQuadIndices(Vector<unsigned short>& indices, unsigned int rowIdx, unsigned int nextRowIdx)
84 indices.PushBack(rowIdx);
85 indices.PushBack(nextRowIdx + 1);
86 indices.PushBack(rowIdx + 1);
88 indices.PushBack(rowIdx);
89 indices.PushBack(nextRowIdx);
90 indices.PushBack(nextRowIdx + 1);
93 void AddVertex(Vector<Vector2>& vertices, unsigned int x, unsigned int y)
95 vertices.PushBack(Vector2(x, y));
98 void RegisterStretchProperties(Renderer& renderer, const char* uniformName, const NPatchUtility::StretchRanges& stretchPixels, uint16_t imageExtent)
100 uint16_t prevEnd = 0;
101 uint16_t prevFix = 0;
102 uint16_t prevStretch = 0;
104 for(NPatchUtility::StretchRanges::ConstIterator it = stretchPixels.Begin(); it != stretchPixels.End(); ++it, ++i)
106 uint16_t start = it->GetX();
107 uint16_t end = it->GetY();
109 uint16_t fix = prevFix + start - prevEnd;
110 uint16_t stretch = prevStretch + end - start;
112 std::stringstream uniform;
113 uniform << uniformName << "[" << i << "]";
114 renderer.RegisterProperty(uniform.str(), Vector2(fix, stretch));
118 prevStretch = stretch;
122 prevFix += imageExtent - prevEnd;
123 std::stringstream uniform;
124 uniform << uniformName << "[" << i << "]";
125 renderer.RegisterProperty(uniform.str(), Vector2(prevFix, prevStretch));
129 } //unnamed namespace
131 /////////////////NPatchVisual////////////////
133 NPatchVisualPtr NPatchVisual::New(VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl, const Property::Map& properties)
135 NPatchVisualPtr nPatchVisual(new NPatchVisual(factoryCache, shaderFactory));
136 nPatchVisual->mImageUrl = imageUrl;
137 nPatchVisual->SetProperties(properties);
138 nPatchVisual->Initialize();
142 NPatchVisualPtr NPatchVisual::New(VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl)
144 NPatchVisualPtr nPatchVisual(new NPatchVisual(factoryCache, shaderFactory));
145 nPatchVisual->mImageUrl = imageUrl;
146 nPatchVisual->Initialize();
150 void NPatchVisual::LoadImages()
152 TextureManager& textureManager = mFactoryCache.GetTextureManager();
153 bool synchronousLoading = mImpl->mFlags & Impl::IS_SYNCHRONOUS_RESOURCE_LOADING;
155 if(mId == NPatchData::INVALID_NPATCH_DATA_ID && mImageUrl.IsLocalResource())
157 bool preMultiplyOnLoad = IsPreMultipliedAlphaEnabled() && !mImpl->mCustomShader ? true : false;
158 mId = mLoader.Load(textureManager, this, mImageUrl.GetUrl(), mBorder, preMultiplyOnLoad, synchronousLoading);
160 const NPatchData* data;
161 if(mLoader.GetNPatchData(mId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
163 EnablePreMultipliedAlpha(data->IsPreMultiplied());
167 if(!mAuxiliaryPixelBuffer && mAuxiliaryUrl.IsValid() && mAuxiliaryUrl.IsLocalResource())
169 // Load the auxiliary image
170 auto preMultiplyOnLoading = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
171 mAuxiliaryPixelBuffer = textureManager.LoadPixelBuffer(mAuxiliaryUrl, Dali::ImageDimensions(), FittingMode::DEFAULT, SamplingMode::BOX_THEN_LINEAR, synchronousLoading, this, true, preMultiplyOnLoading);
175 void NPatchVisual::GetNaturalSize(Vector2& naturalSize)
180 // load now if not already loaded
181 const NPatchData* data;
182 if(mLoader.GetNPatchData(mId, data) && data->GetLoadingState() != NPatchData::LoadingState::LOADING)
184 naturalSize.x = data->GetCroppedWidth();
185 naturalSize.y = data->GetCroppedHeight();
189 if(mImageUrl.IsValid())
191 ImageDimensions dimensions = Dali::GetOriginalImageSize(mImageUrl.GetUrl());
192 if(dimensions != ImageDimensions(0, 0))
194 naturalSize.x = dimensions.GetWidth();
195 naturalSize.y = dimensions.GetHeight();
200 if(mAuxiliaryPixelBuffer)
202 naturalSize.x = std::max(naturalSize.x, float(mAuxiliaryPixelBuffer.GetWidth()));
203 naturalSize.y = std::max(naturalSize.y, float(mAuxiliaryPixelBuffer.GetHeight()));
207 void NPatchVisual::DoSetProperties(const Property::Map& propertyMap)
209 // URL is already passed in via constructor
211 Property::Value* borderOnlyValue = propertyMap.Find(Toolkit::ImageVisual::Property::BORDER_ONLY, BORDER_ONLY);
214 borderOnlyValue->Get(mBorderOnly);
217 Property::Value* borderValue = propertyMap.Find(Toolkit::ImageVisual::Property::BORDER, BORDER);
218 if(borderValue && !borderValue->Get(mBorder)) // If value exists and is rect, just set mBorder
220 // Not a rect so try vector4
222 if(borderValue->Get(border))
224 mBorder.left = static_cast<int>(border.x);
225 mBorder.right = static_cast<int>(border.y);
226 mBorder.bottom = static_cast<int>(border.z);
227 mBorder.top = static_cast<int>(border.w);
231 Property::Value* auxImage = propertyMap.Find(Toolkit::DevelImageVisual::Property::AUXILIARY_IMAGE, AUXILIARY_IMAGE_NAME);
235 if(auxImage->Get(url))
241 Property::Value* auxImageAlpha = propertyMap.Find(Toolkit::DevelImageVisual::Property::AUXILIARY_IMAGE_ALPHA, AUXILIARY_IMAGE_ALPHA_NAME);
244 auxImageAlpha->Get(mAuxiliaryImageAlpha);
247 Property::Value* synchronousLoading = propertyMap.Find(Toolkit::ImageVisual::Property::SYNCHRONOUS_LOADING, SYNCHRONOUS_LOADING);
248 if(synchronousLoading)
251 synchronousLoading->Get(sync);
254 mImpl->mFlags |= Impl::IS_SYNCHRONOUS_RESOURCE_LOADING;
258 mImpl->mFlags &= ~Impl::IS_SYNCHRONOUS_RESOURCE_LOADING;
262 Property::Value* releasePolicy = propertyMap.Find(Toolkit::ImageVisual::Property::RELEASE_POLICY, RELEASE_POLICY_NAME);
265 releasePolicy->Get(mReleasePolicy);
269 void NPatchVisual::DoSetOnScene(Actor& actor)
271 // load when first go on stage
274 const NPatchData* data;
275 if(mLoader.GetNPatchData(mId, data))
277 Geometry geometry = CreateGeometry();
278 Shader shader = CreateShader();
280 mImpl->mRenderer.SetGeometry(geometry);
281 mImpl->mRenderer.SetShader(shader);
283 mPlacementActor = actor;
284 if(data->GetLoadingState() != NPatchData::LoadingState::LOADING)
286 if(RenderingAddOn::Get().IsValid())
288 RenderingAddOn::Get().SubmitRenderTask(mImpl->mRenderer, data->GetRenderingMap());
291 ApplyTextureAndUniforms();
292 actor.AddRenderer(mImpl->mRenderer);
293 mPlacementActor.Reset();
295 // npatch loaded and ready to display
296 ResourceReady(Toolkit::Visual::ResourceStatus::READY);
301 void NPatchVisual::DoSetOffScene(Actor& actor)
303 if((mId != NPatchData::INVALID_NPATCH_DATA_ID) && mReleasePolicy == Toolkit::ImageVisual::ReleasePolicy::DETACHED)
305 mLoader.Remove(mId, this);
306 mImpl->mResourceStatus = Toolkit::Visual::ResourceStatus::PREPARING;
307 mId = NPatchData::INVALID_NPATCH_DATA_ID;
310 actor.RemoveRenderer(mImpl->mRenderer);
311 mPlacementActor.Reset();
314 void NPatchVisual::OnSetTransform()
318 mImpl->mTransform.RegisterUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT);
322 void NPatchVisual::DoCreatePropertyMap(Property::Map& map) const
325 bool sync = IsSynchronousLoadingRequired();
326 map.Insert(Toolkit::ImageVisual::Property::SYNCHRONOUS_LOADING, sync);
327 map.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::N_PATCH);
328 map.Insert(Toolkit::ImageVisual::Property::URL, mImageUrl.GetUrl());
329 map.Insert(Toolkit::ImageVisual::Property::BORDER_ONLY, mBorderOnly);
330 map.Insert(Toolkit::ImageVisual::Property::BORDER, mBorder);
331 map.Insert(Toolkit::ImageVisual::Property::RELEASE_POLICY, mReleasePolicy);
333 if(mAuxiliaryUrl.IsValid())
335 map.Insert(Toolkit::DevelImageVisual::Property::AUXILIARY_IMAGE, mAuxiliaryUrl.GetUrl());
336 map.Insert(Toolkit::DevelImageVisual::Property::AUXILIARY_IMAGE_ALPHA, mAuxiliaryImageAlpha);
340 void NPatchVisual::DoCreateInstancePropertyMap(Property::Map& map) const
342 if(mAuxiliaryUrl.IsValid())
344 map.Insert(Toolkit::DevelImageVisual::Property::AUXILIARY_IMAGE, mAuxiliaryUrl.GetUrl());
345 map.Insert(Toolkit::DevelImageVisual::Property::AUXILIARY_IMAGE_ALPHA, mAuxiliaryImageAlpha);
349 NPatchVisual::NPatchVisual(VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory)
350 : Visual::Base(factoryCache, Visual::FittingMode::FILL, Toolkit::Visual::N_PATCH),
352 mLoader(factoryCache.GetNPatchLoader()),
353 mImageVisualShaderFactory(shaderFactory),
356 mId(NPatchData::INVALID_NPATCH_DATA_ID),
359 mAuxiliaryImageAlpha(0.0f),
360 mReleasePolicy(Toolkit::ImageVisual::ReleasePolicy::DETACHED)
362 EnablePreMultipliedAlpha(mFactoryCache.GetPreMultiplyOnLoad());
365 NPatchVisual::~NPatchVisual()
367 if((mId != NPatchData::INVALID_NPATCH_DATA_ID) && (mReleasePolicy != Toolkit::ImageVisual::ReleasePolicy::NEVER))
369 mLoader.Remove(mId, this);
370 mId = NPatchData::INVALID_NPATCH_DATA_ID;
374 void NPatchVisual::OnInitialize()
376 // Get basic geometry and shader
377 Geometry geometry = mFactoryCache.GetGeometry(VisualFactoryCache::QUAD_GEOMETRY);
378 Shader shader = mImageVisualShaderFactory.GetShader(mFactoryCache, false, true, false);
380 mImpl->mRenderer = Renderer::New(geometry, shader);
382 //Register transform properties
383 mImpl->mTransform.RegisterUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT);
386 Geometry NPatchVisual::CreateGeometry()
389 const NPatchData* data;
390 if(mLoader.GetNPatchData(mId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
392 if(data->GetStretchPixelsX().Size() == 1 && data->GetStretchPixelsY().Size() == 1)
394 if(DALI_UNLIKELY(mBorderOnly))
396 geometry = GetNinePatchGeometry(VisualFactoryCache::NINE_PATCH_BORDER_GEOMETRY);
400 if(data->GetRenderingMap())
402 uint32_t elementCount[2];
403 geometry = RenderingAddOn::Get().CreateGeometryGrid(data->GetRenderingMap(), Uint16Pair(3, 3), elementCount);
406 RenderingAddOn::Get().SubmitRenderTask(mImpl->mRenderer, data->GetRenderingMap());
411 geometry = GetNinePatchGeometry(VisualFactoryCache::NINE_PATCH_GEOMETRY);
415 else if(data->GetStretchPixelsX().Size() > 0 || data->GetStretchPixelsY().Size() > 0)
417 Uint16Pair gridSize(2 * data->GetStretchPixelsX().Size() + 1, 2 * data->GetStretchPixelsY().Size() + 1);
418 if(!data->GetRenderingMap())
420 geometry = !mBorderOnly ? CreateGridGeometry(gridSize) : CreateBorderGeometry(gridSize);
424 uint32_t elementCount[2];
425 geometry = !mBorderOnly ? RenderingAddOn::Get().CreateGeometryGrid(data->GetRenderingMap(), gridSize, elementCount) : CreateBorderGeometry(gridSize);
428 RenderingAddOn::Get().SubmitRenderTask(mImpl->mRenderer, data->GetRenderingMap());
435 // no N patch data so use default geometry
436 geometry = GetNinePatchGeometry(VisualFactoryCache::NINE_PATCH_GEOMETRY);
441 Shader NPatchVisual::CreateShader()
444 const NPatchData* data;
445 // 0 is either no data (load failed?) or no stretch regions on image
446 // for both cases we use the default shader
447 NPatchUtility::StretchRanges::SizeType xStretchCount = 0;
448 NPatchUtility::StretchRanges::SizeType yStretchCount = 0;
450 auto fragmentShader = mAuxiliaryPixelBuffer ? SHADER_NPATCH_VISUAL_MASK_SHADER_FRAG
451 : SHADER_NPATCH_VISUAL_SHADER_FRAG;
452 auto shaderType = mAuxiliaryPixelBuffer ? VisualFactoryCache::NINE_PATCH_MASK_SHADER
453 : VisualFactoryCache::NINE_PATCH_SHADER;
455 // ask loader for the regions
456 if(mLoader.GetNPatchData(mId, data))
458 xStretchCount = data->GetStretchPixelsX().Count();
459 yStretchCount = data->GetStretchPixelsY().Count();
462 if(DALI_LIKELY(!mImpl->mCustomShader))
464 if(DALI_LIKELY((xStretchCount == 1 && yStretchCount == 1) ||
465 (xStretchCount == 0 && yStretchCount == 0)))
467 shader = mFactoryCache.GetShader(shaderType);
468 if(DALI_UNLIKELY(!shader))
470 shader = Shader::New(SHADER_NPATCH_VISUAL_3X3_SHADER_VERT, fragmentShader);
471 // Only cache vanilla 9 patch shaders
472 mFactoryCache.SaveShader(shaderType, shader);
475 else if(xStretchCount > 0 || yStretchCount > 0)
477 std::stringstream vertexShader;
478 vertexShader << "#define FACTOR_SIZE_X " << xStretchCount + 2 << "\n"
479 << "#define FACTOR_SIZE_Y " << yStretchCount + 2 << "\n"
480 << SHADER_NPATCH_VISUAL_SHADER_VERT;
482 shader = Shader::New(vertexShader.str(), fragmentShader);
487 Dali::Shader::Hint::Value hints = Dali::Shader::Hint::NONE;
489 if(!mImpl->mCustomShader->mFragmentShader.empty())
491 fragmentShader = mImpl->mCustomShader->mFragmentShader.c_str();
493 hints = mImpl->mCustomShader->mHints;
495 /* Apply Custom Vertex Shader only if image is 9-patch */
496 if((xStretchCount == 1 && yStretchCount == 1) ||
497 (xStretchCount == 0 && yStretchCount == 0))
499 const char* vertexShader = SHADER_NPATCH_VISUAL_3X3_SHADER_VERT.data();
501 if(!mImpl->mCustomShader->mVertexShader.empty())
503 vertexShader = mImpl->mCustomShader->mVertexShader.c_str();
505 shader = Shader::New(vertexShader, fragmentShader, hints);
507 else if(xStretchCount > 0 || yStretchCount > 0)
509 std::stringstream vertexShader;
510 vertexShader << "#define FACTOR_SIZE_X " << xStretchCount + 2 << "\n"
511 << "#define FACTOR_SIZE_Y " << yStretchCount + 2 << "\n"
512 << SHADER_NPATCH_VISUAL_SHADER_VERT;
514 shader = Shader::New(vertexShader.str(), fragmentShader, hints);
521 void NPatchVisual::ApplyTextureAndUniforms()
523 const NPatchData* data;
524 TextureSet textureSet;
526 if(mLoader.GetNPatchData(mId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
528 textureSet = data->GetTextures();
530 if(data->GetStretchPixelsX().Size() == 1 && data->GetStretchPixelsY().Size() == 1)
532 //special case for 9 patch
533 Uint16Pair stretchX = data->GetStretchPixelsX()[0];
534 Uint16Pair stretchY = data->GetStretchPixelsY()[0];
536 uint16_t stretchWidth = (stretchX.GetY() >= stretchX.GetX()) ? stretchX.GetY() - stretchX.GetX() : 0;
537 uint16_t stretchHeight = (stretchY.GetY() >= stretchY.GetX()) ? stretchY.GetY() - stretchY.GetX() : 0;
539 mImpl->mRenderer.RegisterProperty("uFixed[0]", Vector2::ZERO);
540 mImpl->mRenderer.RegisterProperty("uFixed[1]", Vector2(stretchX.GetX(), stretchY.GetX()));
541 mImpl->mRenderer.RegisterProperty("uFixed[2]", Vector2(data->GetCroppedWidth() - stretchWidth, data->GetCroppedHeight() - stretchHeight));
542 mImpl->mRenderer.RegisterProperty("uStretchTotal", Vector2(stretchWidth, stretchHeight));
546 mImpl->mRenderer.RegisterProperty("uNinePatchFactorsX[0]", Vector2::ZERO);
547 mImpl->mRenderer.RegisterProperty("uNinePatchFactorsY[0]", Vector2::ZERO);
549 RegisterStretchProperties(mImpl->mRenderer, "uNinePatchFactorsX", data->GetStretchPixelsX(), data->GetCroppedWidth());
550 RegisterStretchProperties(mImpl->mRenderer, "uNinePatchFactorsY", data->GetStretchPixelsY(), data->GetCroppedHeight());
555 DALI_LOG_ERROR("The N patch image '%s' is not a valid N patch image\n", mImageUrl.GetUrl().c_str());
556 textureSet = TextureSet::New();
558 Texture croppedImage = mFactoryCache.GetBrokenVisualImage();
559 textureSet.SetTexture(0u, croppedImage);
560 mImpl->mRenderer.RegisterProperty("uFixed[0]", Vector2::ZERO);
561 mImpl->mRenderer.RegisterProperty("uFixed[1]", Vector2::ZERO);
562 mImpl->mRenderer.RegisterProperty("uFixed[2]", Vector2::ZERO);
563 mImpl->mRenderer.RegisterProperty("uStretchTotal", Vector2(croppedImage.GetWidth(), croppedImage.GetHeight()));
566 if(mAuxiliaryPixelBuffer)
568 // If the auxiliary image is smaller than the un-stretched NPatch, use CPU resizing to enlarge it to the
569 // same size as the unstretched NPatch. This will give slightly higher quality results than just relying
570 // on GL interpolation alone.
571 if(mAuxiliaryPixelBuffer.GetWidth() < data->GetCroppedWidth() &&
572 mAuxiliaryPixelBuffer.GetHeight() < data->GetCroppedHeight())
574 mAuxiliaryPixelBuffer.Resize(data->GetCroppedWidth(), data->GetCroppedHeight());
577 // Note, this resets mAuxiliaryPixelBuffer handle
578 auto auxiliaryPixelData = Devel::PixelBuffer::Convert(mAuxiliaryPixelBuffer);
580 auto texture = Texture::New(TextureType::TEXTURE_2D,
581 auxiliaryPixelData.GetPixelFormat(),
582 auxiliaryPixelData.GetWidth(),
583 auxiliaryPixelData.GetHeight());
584 texture.Upload(auxiliaryPixelData);
585 textureSet.SetTexture(1, texture);
586 mImpl->mRenderer.RegisterProperty(DevelImageVisual::Property::AUXILIARY_IMAGE_ALPHA,
587 AUXILIARY_IMAGE_ALPHA_NAME,
588 mAuxiliaryImageAlpha);
590 mImpl->mRenderer.SetTextures(textureSet);
592 // Register transform properties
593 mImpl->mTransform.RegisterUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT);
596 Geometry NPatchVisual::GetNinePatchGeometry(VisualFactoryCache::GeometryType subType)
598 Geometry geometry = mFactoryCache.GetGeometry(subType);
601 if(DALI_LIKELY(VisualFactoryCache::NINE_PATCH_GEOMETRY == subType))
603 geometry = CreateGridGeometry(Uint16Pair(3, 3));
605 else if(VisualFactoryCache::NINE_PATCH_BORDER_GEOMETRY == subType)
607 geometry = CreateBorderGeometry(Uint16Pair(3, 3));
609 mFactoryCache.SaveGeometry(subType, geometry);
614 Geometry NPatchVisual::CreateGridGeometry(Uint16Pair gridSize)
616 uint16_t gridWidth = gridSize.GetWidth();
617 uint16_t gridHeight = gridSize.GetHeight();
620 Vector<Vector2> vertices;
621 vertices.Reserve((gridWidth + 1) * (gridHeight + 1));
623 for(int y = 0; y < gridHeight + 1; ++y)
625 for(int x = 0; x < gridWidth + 1; ++x)
627 AddVertex(vertices, x, y);
632 Vector<unsigned short> indices;
633 indices.Reserve(gridWidth * gridHeight * 6);
635 unsigned int rowIdx = 0;
636 unsigned int nextRowIdx = gridWidth + 1;
637 for(int y = 0; y < gridHeight; ++y, ++nextRowIdx, ++rowIdx)
639 for(int x = 0; x < gridWidth; ++x, ++nextRowIdx, ++rowIdx)
641 AddQuadIndices(indices, rowIdx, nextRowIdx);
645 return GenerateGeometry(vertices, indices);
648 Geometry NPatchVisual::CreateBorderGeometry(Uint16Pair gridSize)
650 uint16_t gridWidth = gridSize.GetWidth();
651 uint16_t gridHeight = gridSize.GetHeight();
654 Vector<Vector2> vertices;
655 vertices.Reserve((gridWidth + 1) * (gridHeight + 1));
661 for(int x = 0; x < gridWidth + 1; ++x)
663 AddVertex(vertices, x, y);
667 for(; y < gridHeight - 1; ++y)
670 AddVertex(vertices, 0, y);
671 AddVertex(vertices, 1, y);
674 AddVertex(vertices, gridWidth - 1, y);
675 AddVertex(vertices, gridWidth, y);
679 for(; y < gridHeight + 1; ++y)
681 for(int x = 0; x < gridWidth + 1; ++x)
683 AddVertex(vertices, x, y);
688 Vector<unsigned short> indices;
689 indices.Reserve(gridWidth * gridHeight * 6);
692 unsigned int rowIdx = 0;
693 unsigned int nextRowIdx = gridWidth + 1;
694 for(int x = 0; x < gridWidth; ++x, ++nextRowIdx, ++rowIdx)
696 AddQuadIndices(indices, rowIdx, nextRowIdx);
701 rowIdx = gridWidth + 1;
702 nextRowIdx = (gridWidth + 1) * 2;
704 unsigned increment = gridWidth - 1;
709 AddQuadIndices(indices, rowIdx, nextRowIdx);
711 rowIdx = gridWidth * 2;
712 nextRowIdx = (gridWidth + 1) * 2 + 2;
714 AddQuadIndices(indices, rowIdx, nextRowIdx);
717 rowIdx = nextRowIdx - 2;
718 nextRowIdx = rowIdx + 4;
719 for(int y = 2; y < 2 * (gridHeight - 3); ++y, rowIdx += 2, nextRowIdx += 2)
721 AddQuadIndices(indices, rowIdx, nextRowIdx);
726 AddQuadIndices(indices, rowIdx, nextRowIdx);
729 nextRowIdx += gridWidth - 1;
731 AddQuadIndices(indices, rowIdx, nextRowIdx);
735 rowIdx = nextRowIdx - gridWidth + 1;
736 nextRowIdx = rowIdx + gridWidth + 1;
737 for(int x = 0; x < gridWidth; ++x, ++nextRowIdx, ++rowIdx)
739 AddQuadIndices(indices, rowIdx, nextRowIdx);
742 return GenerateGeometry(vertices, indices);
745 void NPatchVisual::SetResource()
747 const NPatchData* data;
748 if(mImpl->mRenderer && mLoader.GetNPatchData(mId, data))
750 Geometry geometry = CreateGeometry();
751 Shader shader = CreateShader();
753 mImpl->mRenderer.SetGeometry(geometry);
754 mImpl->mRenderer.SetShader(shader);
756 Actor actor = mPlacementActor.GetHandle();
759 ApplyTextureAndUniforms();
760 actor.AddRenderer(mImpl->mRenderer);
761 mPlacementActor.Reset();
763 // npatch loaded and ready to display
764 ResourceReady(Toolkit::Visual::ResourceStatus::READY);
769 void NPatchVisual::UploadComplete(bool loadSuccess, int32_t textureId, TextureSet textureSet, bool useAtlasing, const Vector4& atlasRect, bool preMultiplied)
771 EnablePreMultipliedAlpha(preMultiplied);
774 // Image loaded and ready to display
775 ResourceReady(Toolkit::Visual::ResourceStatus::FAILED);
778 if(mAuxiliaryPixelBuffer || !mAuxiliaryUrl.IsValid())
784 void NPatchVisual::LoadComplete(bool loadSuccess, Devel::PixelBuffer pixelBuffer, const VisualUrl& url, bool preMultiplied)
786 if(loadSuccess && url.GetUrl() == mAuxiliaryUrl.GetUrl())
788 mAuxiliaryPixelBuffer = pixelBuffer;
793 // Image loaded and ready to display
794 ResourceReady(Toolkit::Visual::ResourceStatus::FAILED);
798 } // namespace Internal
800 } // namespace Toolkit