Esempio n. 1
0
        internal override void NowOffScreen()
        {
            if (ImageLocation == null)
            {
                return;
            }

            if (ImageLocation.DecreaseUsage())
            {
                ImageLocation = null;
            }
        }
Esempio n. 2
0
        /// <summary>Called when this character goes on screen.</summary>
        public void OnScreen()
        {
            if (Location == null && FirstPathNode != null)
            {
                Location = AtlasStacks.Text.RequireImage(this);
            }

            if (Location != null)
            {
                Location.UsageCount++;
            }
        }
Esempio n. 3
0
        /// <summary>Called when this character goes on screen.</summary>
        public void OffScreen()
        {
            if (Location == null)
            {
                return;
            }

            if (Location.DecreaseUsage())
            {
                Location = null;
            }
        }
Esempio n. 4
0
        protected override bool NowOnScreen()
        {
            if (Image == null || Image.Image == null)
            {
                // Reject the visibility state change.
                ImageLocation = null;
                return(false);
            }

            ImageLocation = RequireImage(Image);

            return(true);
        }
Esempio n. 5
0
        public AtlasLocation RequireImage(AtlasEntity image)
        {
            // Get the image from the global atlas stack.
            AtlasLocation location = AtlasStacks.Graphics.RequireImage(image);

            if (location == null)
            {
                // It's separate from the atlas. Too big to fit/ not worth being on an atlas.
                Isolate();
            }
            else
            {
                location.UsageCount++;
                Include();
            }

            return(location);
        }
Esempio n. 6
0
        public bool DrawToAtlas(TextureAtlas atlas, AtlasLocation location)
        {
            // Only ever called with a static image:
            Color32[] pixelBlock = Image.GetPixels32();

            int index      = 0;
            int atlasIndex = location.BottomLeftPixel();

            int height = Image.height;
            int width  = Image.width;

            // How many pixels must we add on to the end of the row to get to
            // the start of the row above? This is simply the dimension of the atlas:
            int rowDelta = atlas.Dimension;

            for (int h = 0; h < height; h++)
            {
                Array.Copy(pixelBlock, index, atlas.Pixels, atlasIndex, width);
                index      += width;
                atlasIndex += rowDelta;
            }

            return(true);
        }
Esempio n. 7
0
        internal override bool NowOnScreen()
        {
            if (Image == null || !Image.Loaded)
            {
                // Reject the visibility state change.
                ImageLocation = null;
                return(false);
            }

            // Tell it that it's going on screen:
            Image.GoingOnDisplay(RenderData);

            // Must be PictureFormat to go onto the atlas:
            PictureFormat picture = Image.Contents as PictureFormat;

            if (picture == null)
            {
                // Reject the visibility state change (only available to images).
                ImageLocation = null;
                return(false);
            }

            if (Isolated)
            {
                if (ImageLocation != null)
                {
                    ImageLocation.DecreaseUsage();
                    ImageLocation = null;
                }
                return(true);
            }

            ImageLocation = RequireImage(Image);

            return(true);
        }
Esempio n. 8
0
 public bool DrawToAtlas(TextureAtlas atlas, AtlasLocation location)
 {
     return(Contents.DrawToAtlas(atlas, location));
 }
Esempio n. 9
0
        protected override void Layout()
        {
            if (Image == null || !Image.Loaded())
            {
                return;
            }

            if (Clipping == BackgroundClipping.Text)
            {
                return;
            }

            Renderman renderer = Element.Document.Renderer;

            if (Image.Animated || Image.IsDynamic || renderer.RenderMode == RenderMode.NoAtlas || Filtering != FilterMode.Point || ForcedIsolate)
            {
                // SPA is an animation format, so we need a custom texture atlas to deal with it.
                // This is because the frames of any animation would quickly exhaust our global texture atlas.
                // So to get a custom atlas, we must isolate this property.
                Isolate();
            }
            else if (Image.IsVideo)
            {
                // Similarly with a video, we need to isolate it aswell.
                Isolate();

                                #if !MOBILE
                if (!Image.Video.isPlaying && Element["autoplay"] != null)
                {
                    // Play now:
                    Image.Video.Play();

                    // Fire an onplay event:
                    Element.Run("onplay");

                    // Clear:
                    Element["autoplay"] = null;
                }
                                #endif
            }
            else
            {
                // Reverse isolation, if we are isolated already:
                Include();
            }

            ComputedStyle computed = Element.Style.Computed;

            // Get the full shape of the element:
            int width  = computed.PaddedWidth;
            int height = computed.PaddedHeight;
            int minY   = computed.OffsetTop + computed.BorderTop;
            int minX   = computed.OffsetLeft + computed.BorderLeft;

            if (width == 0 || height == 0)
            {
                if (Visible)
                {
                    SetVisibility(false);
                }
                return;
            }

            BoxRegion boundary = new BoxRegion(minX, minY, width, height);

            if (!boundary.Overlaps(renderer.ClippingBoundary))
            {
                if (Visible)
                {
                    SetVisibility(false);
                }

                return;
            }
            else if (!Visible)
            {
                // ImageLocation will allocate here if it's needed.
                SetVisibility(true);
            }

            boundary.ClipBy(renderer.ClippingBoundary);

            // Texture time - get it's location on that atlas:
            AtlasLocation locatedAt = ImageLocation;

            if (locatedAt == null)
            {
                // We're not using the atlas here.

                if (!Isolated)
                {
                    Isolate();
                }

                int imgWidth  = Image.Width();
                int imgHeight = Image.Height();
                locatedAt = new AtlasLocation(0, 0, imgWidth, imgHeight, imgWidth, imgHeight);
            }

            // Isolation is all done - safe to setup the batch now:
            SetupBatch(locatedAt.Atlas, null);

            // Great - Use locatedAt.Width/locatedAt.Height - this removes any risk of overflowing into some other image.

            int  imageCountX     = 1;
            int  imageCountY     = 1;
            int  trueImageWidth  = locatedAt.Width;
            int  trueImageHeight = locatedAt.Height;
            int  imageWidth      = trueImageWidth;
            int  imageHeight     = trueImageHeight;
            bool autoX           = false;
            bool autoY           = false;

            if (Image.PixelPerfect)
            {
                imageWidth  = (int)(imageWidth * ScreenInfo.ResolutionScale);
                imageHeight = (int)(imageWidth * ScreenInfo.ResolutionScale);
            }

            if (SizeX != null)
            {
                if (SizeX.Single != 0f)
                {
                    imageWidth = (int)(width * SizeX.Single);
                }
                else if (SizeX.PX != 0)
                {
                    imageWidth = SizeX.PX;
                }
                else if (SizeX.IsAuto())
                {
                    autoX = true;
                }
            }

            if (SizeY != null)
            {
                if (SizeY.Single != 0f)
                {
                    imageHeight = (int)(height * SizeY.Single);
                }
                else if (SizeY.PX != 0)
                {
                    imageHeight = SizeY.PX;
                }
                else if (SizeY.IsAuto())
                {
                    autoY = true;
                }
            }

            if (autoX)
            {
                imageWidth = imageHeight * trueImageWidth / trueImageHeight;
            }
            else if (autoY)
            {
                imageHeight = imageWidth * trueImageHeight / trueImageWidth;
            }

            // offsetX and offsetY are the images position offset from where it should be (e.g. x of -200 means it's 200px left)

            // Resolve the true offset values:
            int offsetX = 0;
            int offsetY = 0;

            if (OffsetX != null)
            {
                // Resolve a potential mixed % and px:
                offsetX = OffsetX.GetMixed(width - imageWidth);
            }

            if (OffsetY != null)
            {
                // Resolve a potential mixed % and px:
                offsetY = OffsetY.GetMixed(height - imageHeight);
            }

            if (RepeatX)
            {
                // Get the rounded up number of images:
                imageCountX = (width - 1) / imageWidth + 1;

                if (offsetX != 0)
                {
                    // If we have an offset, another image is introduced.
                    imageCountX++;
                }
            }

            if (RepeatY)
            {
                // Get the rounded up number of images:
                imageCountY = (height - 1) / imageHeight + 1;
                if (offsetY != 0)
                {
                    // If we have an offset, another image is introduced.
                    imageCountY++;
                }
            }

            int blockX = minX + offsetX;
            int blockY = minY + offsetY;

            if (RepeatX && offsetX > 0)
            {
                // We're repeating and the image is offset by a +ve number.
                // This means a small gap, OffsetX px wide, is open on this left side.
                // So to fill it, we need to offset this first image by a much bigger number - the value imageWidth-OffsetX.
                blockX -= (imageWidth - offsetX);
                // This results in the first image having OffsetX pixels exposed in the box - this is what we want.
            }

            if (RepeatY && offsetY > 0)
            {
                // Similar thing to above:
                blockY -= (imageHeight - offsetY);
            }

            BoxRegion screenRegion = new BoxRegion();

            bool  first  = true;
            int   startX = blockX;
            Color colour = computed.ColorOverlay;
            float zIndex = (computed.ZIndex - 0.003f);

            for (int y = 0; y < imageCountY; y++)
            {
                for (int x = 0; x < imageCountX; x++)
                {
                    // Draw at blockX/blockY.
                    screenRegion.Set(blockX, blockY, imageWidth, imageHeight);

                    if (screenRegion.Overlaps(boundary))
                    {
                        // If the two overlap, this means it's actually visible.
                        MeshBlock block = Add();

                        if (Image.Animated && first)
                        {
                            first = false;
                            // Make sure we have an instance:
                            Image.GoingOnDisplay();
                            block.ParentMesh.SetMaterial(Image.Animation.AnimatedMaterial);
                        }
                        else if (Image.IsVideo && first)
                        {
                            first = false;
                            block.ParentMesh.SetMaterial(Image.VideoMaterial);
                        }
                        else if (Isolated && first)
                        {
                            first = false;
                            block.ParentMesh.SetMaterial(Image.ImageMaterial);
                        }

                        // Set it's colour:
                        block.SetColour(colour);

                        // And clip our meshblock to fit within boundary:
                        block.TextUV  = null;
                        block.ImageUV = block.SetClipped(boundary, screenRegion, renderer, zIndex, locatedAt, block.ImageUV);
                    }

                    blockX += imageWidth;
                }
                blockX  = startX;
                blockY += imageHeight;
            }
        }
Esempio n. 10
0
 /// <summary>Draws this image to the given atlas.</summary>
 public virtual bool DrawToAtlas(TextureAtlas atlas, AtlasLocation location)
 {
     return(false);
 }
        /// <summary>Draws a character with x-inverted UV's. Used for rendering e.g. "1 < 2" in right-to-left.</summary>
        protected virtual void DrawInvertCharacter(ref float left, Renderman renderer)
        {
            BoxRegion screenRegion = renderer.CurrentRegion;
            float     top          = renderer.TopOffset;
            int       index        = renderer.CharacterIndex;

            Glyph character = Characters[index];

            if (character == null)
            {
                return;
            }

            if (Kerning != null)
            {
                left += Kerning[index] * FontSize;
            }

            // Get atlas location (if it has one):
            AtlasLocation locatedAt = character.Location;

            if (locatedAt != null)
            {
                // We're on the atlas!

                float y = top + renderer.TextAscender - ((character.Height + character.MinY) * FontSize);

                float scaleFactor = renderer.TextScaleFactor;

                screenRegion.Set(left + (character.LeftSideBearing * FontSize), y, locatedAt.Width * scaleFactor, locatedAt.Height * scaleFactor);

                if (screenRegion.Overlaps(renderer.ClippingBoundary))
                {
                    // True if this character is visible.

                    // Ensure correct batch:
                    renderer.SetupBatch(this, null, locatedAt.Atlas);

                    MeshBlock block = Add(renderer);
                    block.SetColour(renderer.FontColour);
                    block.ApplyOutline();

                    // And clip our meshblock to fit within boundary:

                    // Clip our meshblock to fit within boundary:
                    if (Background != null && Isolated)
                    {
                        // Setup the batch material for this char:
                        Material imageMaterial = Background.Image.Contents.GetImageMaterial(renderer.CurrentShaderSet.Normal);
                        SetBatchMaterial(renderer, imageMaterial);

                        // Reapply text atlas:
                        renderer.CurrentBatch.SetFontAtlas(locatedAt.Atlas);

                        // Apply the image UV's (we're always isolated so these can tile by going out of range):
                        block.ImageUV = block.SetClipped(
                            renderer.ClippingBoundary,
                            screenRegion,
                            renderer,
                            RenderData.computedStyle.ZIndex,
                            Background.ImageLocation,
                            block.ImageUV
                            );
                    }
                    else
                    {
                        block.ImageUV = null;
                    }

                    UVBlock uvs = block.SetClipped(renderer.ClippingBoundary, screenRegion, renderer, RenderData.computedStyle.ZIndex, locatedAt, block.TextUV);

                    if (uvs.Shared)
                    {
                        uvs = new UVBlock(uvs);
                    }

                    // Invert along X:
                    float temp = uvs.MinX;
                    uvs.MinX = uvs.MaxX;
                    uvs.MaxX = temp;

                    // Assign to the block:
                    block.TextUV = uvs;

                    block.Done(renderer.Transform);
                }
            }

            left += (character.AdvanceWidth * FontSize) + LetterSpacing;

            if (character.Charcode == (int)' ')
            {
                left += WordSpacing;
            }
        }
Esempio n. 12
0
        internal override void Layout(LayoutBox box, Renderman renderer)
        {
            if (Image == null || !Image.Loaded)
            {
                return;
            }

            if (Clipping == BackgroundClipping.Text)
            {
                return;
            }

            if (Image.Contents.Isolate || renderer.RenderMode == RenderMode.NoAtlas || Filtering != FilterMode.Point || ForcedIsolate)
            {
                // SPA is an animation format, so we need a custom texture atlas to deal with it.
                // This is because the frames of any animation would quickly exhaust our global texture atlas.
                // So to get a custom atlas, we must isolate this property.
                Isolate();
            }
            else
            {
                // Reverse isolation, if we are isolated already:
                Include();
            }

            // Get the full shape of the element:

            float width;
            float height;
            float minX;
            float minY;

            if (renderer.ViewportBackground)
            {
                // Applying to whole background:
                BoxRegion viewport = renderer.Viewport;

                minY   = (int)viewport.Y;
                minX   = (int)viewport.X;
                width  = (int)viewport.Width;
                height = (int)viewport.Height;

                renderer.ViewportBackground = false;
            }
            else
            {
                width  = (int)(box.PaddedWidth);
                height = (int)(box.PaddedHeight);
                minY   = (int)(box.Y + box.Border.Top);
                minX   = (int)(box.X + box.Border.Left);
            }

            if (width == 0 || height == 0)
            {
                if (Visible)
                {
                    SetVisibility(false);
                }
                return;
            }

            // Tell the image that the box has likely changed - this allows it to redraw (e.g. SVGs):
            float trueImageWidth;
            float trueImageHeight;

            Image.Contents.OnLayout(RenderData, box, out trueImageWidth, out trueImageHeight);

            BoxRegion boundary = new BoxRegion(minX, minY, width, height);

            if (!boundary.Overlaps(renderer.ClippingBoundary))
            {
                if (Visible)
                {
                    SetVisibility(false);
                }

                return;
            }
            else if (!Visible)
            {
                // ImageLocation will allocate here if it's needed.
                SetVisibility(true);
            }

            boundary.ClipBy(renderer.ClippingBoundary);

            // Texture time - get it's location on that atlas:
            AtlasLocation locatedAt = ImageLocation;

            if (locatedAt == null)
            {
                // We're not using the atlas here.

                if (!Isolated)
                {
                    Isolate();
                }

                locatedAt = new AtlasLocation(trueImageWidth, trueImageHeight);
            }

            // Isolation is all done - safe to setup the batch now:
            renderer.SetupBatch(this, locatedAt.Atlas, null);

            // Great - Use locatedAt.Width/locatedAt.Height - this removes any risk of overflowing into some other image.

            int   imageCountX = 1;
            int   imageCountY = 1;
            float imageWidth  = trueImageWidth * RenderData.ValueScale;
            float imageHeight = trueImageHeight * RenderData.ValueScale;
            bool  autoX       = false;
            bool  autoY       = false;

            if (SizeX != null)
            {
                if (SizeX.IsAuto)
                {
                    autoX = true;
                }
                else
                {
                    imageWidth = SizeX.GetDecimal(RenderData, Css.Properties.BackgroundSize.GlobalPropertyX);
                }
            }

            if (SizeY != null)
            {
                if (SizeY.IsAuto)
                {
                    autoY = true;
                }
                else
                {
                    imageHeight = SizeY.GetDecimal(RenderData, Css.Properties.BackgroundSize.GlobalPropertyY);
                }
            }

            if (autoX)
            {
                imageWidth = imageHeight * trueImageWidth / trueImageHeight;
            }
            else if (autoY)
            {
                imageHeight = imageWidth * trueImageHeight / trueImageWidth;
            }

            // offsetX and offsetY are the images position offset from where it should be (e.g. x of -200 means it's 200px left)

            // Apply the offset origin:
            float offsetX = OffsetOriginX * (width - imageWidth);
            float offsetY = OffsetOriginY * (height - imageHeight);

            float offset;

            // Resolve the offset values, if there is any:
            if (OffsetX != null)
            {
                offset = OffsetX.GetDecimal(RenderData, ValueAxis.X);

                if (OffsetOriginX == 1f)
                {
                    offsetX -= offset;
                }
                else
                {
                    offsetX += offset;
                }
            }

            if (OffsetY != null)
            {
                offset = OffsetY.GetDecimal(RenderData, ValueAxis.Y);

                if (OffsetOriginY == 1f)
                {
                    offsetY -= offset;
                }
                else
                {
                    offsetY += offset;
                }
            }

            if (RepeatX)
            {
                // Get the rounded up number of images:
                imageCountX = (int)Math.Ceiling(width / imageWidth);

                if (offsetX != 0)
                {
                    // If we have an offset, another image is introduced.
                    imageCountX++;
                }
            }

            if (RepeatY)
            {
                // Get the rounded up number of images:
                imageCountY = (int)Math.Ceiling(height / imageHeight);
                if (offsetY != 0)
                {
                    // If we have an offset, another image is introduced.
                    imageCountY++;
                }
            }

            float blockX = minX + offsetX;
            float blockY = minY + offsetY;

            if (RepeatX && offsetX > 0)
            {
                // We're repeating and the image is offset by a +ve number.
                // This means a small gap, OffsetX px wide, is open on this left side.
                // So to fill it, we need to offset this first image by a much bigger number - the value imageWidth-OffsetX.
                blockX -= (imageWidth - offsetX);
                // This results in the first image having OffsetX pixels exposed in the box - this is what we want.
            }

            if (RepeatY && offsetY > 0)
            {
                // Similar thing to above:
                blockY -= (imageHeight - offsetY);
            }

            BoxRegion screenRegion = new BoxRegion();

            bool  first  = true;
            float startX = blockX;
            Color colour = renderer.ColorOverlay;
            float zIndex = (RenderData.computedStyle.ZIndex - 0.003f);

            Transformation transform = renderer.Transform;

            for (int y = 0; y < imageCountY; y++)
            {
                for (int x = 0; x < imageCountX; x++)
                {
                    // Draw at blockX/blockY.
                    screenRegion.Set(blockX, blockY, imageWidth, imageHeight);

                    if (screenRegion.Overlaps(boundary))
                    {
                        // If the two overlap, this means it's actually visible.
                        MeshBlock block = Add(renderer);

                        if (first)
                        {
                            first = false;

                            if (Isolated)
                            {
                                // Set current material:
                                SetBatchMaterial(renderer, Image.Contents.GetImageMaterial(renderer.CurrentShaderSet.Isolated));
                            }
                        }

                        // Set its colour:
                        block.SetColour(colour);

                        // And clip our meshblock to fit within boundary:
                        block.TextUV  = null;
                        block.ImageUV = block.SetClipped(boundary, screenRegion, renderer, zIndex, locatedAt, block.ImageUV);

                        block.Done(transform);
                    }

                    blockX += imageWidth;
                }
                blockX  = startX;
                blockY += imageHeight;
            }
        }
Esempio n. 13
0
        /// <summary>Sets the vertices of this box to that specified by the given block
        /// but clipped to fit within a boundary. At the same time, an image is applied
        /// to the block and its UV coordinates are also clipped.</summary>
        /// <param name="boundary">The clipping boundary. The vertices will be clipped to within this.</param>
        /// <param name="block">The position of the vertices.</param>
        /// <param name="renderer">The renderer that will render this block.</param>
        /// <param name="zIndex">The depth of the vertices.</param>
        /// <param name="imgLocation">The location of the image on the meshes atlas.</param>
        public UVBlock SetClipped(BoxRegion boundary, BoxRegion block, Renderman renderer, float zIndex, AtlasLocation imgLocation, UVBlock uvBlock)
        {
            // Image defines how big we want the image to be in pixels on the screen.
            // So firstly we need to find the ratio of how scaled our image actually is:
            float originalHeight = block.Height;
            float scaleX         = imgLocation.Width / block.Width;
            float scaleY         = imgLocation.Height / originalHeight;

            // We'll need to clip block and make sure the image block is clipped too:
            float blockX = block.X;
            float blockY = block.Y;

            if (block.ClipByChecked(boundary))
            {
                // It actually got clipped - time to do some UV clipping too.

                // Apply the verts:
                ApplyVertices(block, renderer, zIndex);

                block.X    -= blockX;
                block.Y    -= blockY;
                block.MaxX -= blockX;
                block.MaxY -= blockY;

                // Flip the gaps (the clipped and now 'missing' sections) - UV's are inverted relative to the vertices.

                // Bottom gap is just block.Y:
                float bottomGap = block.Y;

                // Top gap is the original height - the new maximum; write it to the bottom gap:
                block.Y = originalHeight - block.MaxY;

                // Update the top gap:
                block.MaxY = originalHeight - bottomGap;

                // Image was in terms of real screen pixels, so now we need to scale it to being in 'actual image' pixels.
                // From there, the region
                block.X    *= scaleX;
                block.MaxX *= scaleX;

                block.Y    *= scaleY;
                block.MaxY *= scaleY;

                if (uvBlock == null || uvBlock.Shared)
                {
                    // Create the UV block:
                    uvBlock = new UVBlock();
                }

                // Get the new max/min values:
                uvBlock.MinX = imgLocation.GetU(block.X + 0.2f);
                uvBlock.MaxX = imgLocation.GetU(block.MaxX - 0.2f);
                uvBlock.MaxY = imgLocation.GetV(block.MaxY - 0.2f);
                uvBlock.MinY = imgLocation.GetV(block.Y + 0.2f);
            }
            else
            {
                // Apply the verts:
                ApplyVertices(block, renderer, zIndex);

                // Globally share the UV!
                uvBlock = imgLocation;
            }

            return(uvBlock);
        }
        internal override void Layout(LayoutBox box, Renderman renderer)
        {
            // Dimensions:
            float width  = box.Width;
            float height = box.Height;

            if (Renderer == null)
            {
                // Create the FWUI now:
                Renderer = new FlatWorldUI("#Internal-PowerUI-Raster-" + RasterID, (int)width, (int)height);
                RasterID++;

                if (Filter != null)
                {
                    // Set source:
                    Filter.Set("source0", Renderer.Texture);
                }

                // Grab the output texture:
                Output = Renderer.Texture;
            }

            // Does the given renderer belong to the worldUI?
            if (renderer == Renderer.Renderer)
            {
                // Yes! We're actually drawing the element.

                return;
            }

            // Next we'll draw the rastered image.
            // It's essentially just the output from the renderer.

            // Get the top left inner corner (inside margin and border):
            float top  = box.Y;
            float left = box.X;

            // Update the FlatWorldUI next:
            UpdateRenderer(box, width, height);

            // Always isolated:
            Isolate();

            // Make sure the renderer stalls and doesn't draw anything else of this element or its kids.
            renderer.StallStatus = 2;

            // Setup boundary:
            BoxRegion boundary = new BoxRegion(left, top, width, height);

            if (!boundary.Overlaps(renderer.ClippingBoundary))
            {
                if (Visible)
                {
                    SetVisibility(false);
                }

                return;
            }
            else if (!Visible)
            {
                // ImageLocation will allocate here if it's needed.
                SetVisibility(true);
            }

            // Texture time - get its location on that atlas:
            if (LocatedAt == null)
            {
                LocatedAt = new AtlasLocation(width, height);
            }
            else
            {
                // Dimensions changed?
                int w = (int)width;
                int h = (int)height;

                if (LocatedAt.Width != w || LocatedAt.Height != h)
                {
                    // Update it:
                    LocatedAt.UpdateFixed(width, height);
                }
            }

            boundary.ClipBy(renderer.ClippingBoundary);

            // Ensure we have a batch:
            renderer.SetupBatch(this, null, null);

            if (Material == null)
            {
                // Create the material now using the isolated shader:
                Material = new Material(renderer.CurrentShaderSet.Isolated);

                // Hook up the output:
                Material.SetTexture("_MainTex", Output);
            }

            // Allocate the block:
            MeshBlock block = Add(renderer);

            // Set current material:
            SetBatchMaterial(renderer, Material);

            // Set the (overlay) colour:
            block.SetColour(renderer.ColorOverlay);
            block.TextUV = null;

            // Z-index (same as a background-image):
            float zIndex = (RenderData.computedStyle.ZIndex - 0.003f);

            BoxRegion screenRegion = new BoxRegion();

            screenRegion.Set(left, top, width, height);

            // Setup the block:
            block.ImageUV = block.SetClipped(boundary, screenRegion, renderer, zIndex, LocatedAt, block.ImageUV);

            // Flush it:
            block.Done(renderer.Transform);
        }
Esempio n. 15
0
        /// <summary>Draws a character with x-inverted UV's. Used for rendering e.g. "1 < 2" in right-to-left.</summary>
        protected virtual void DrawInvertCharacter(ref float left, Renderman renderer)
        {
            BoxRegion screenRegion = renderer.CurrentRegion;
            float     top          = renderer.TopOffset;
            int       index        = renderer.CharacterIndex;

            Glyph character = Text.Characters[index];

            if (character == null)
            {
                return;
            }

            if (Text.Kerning != null)
            {
                left += Text.Kerning[index] * Text.FontSize;
            }

            // Get atlas location (if it has one):
            AtlasLocation locatedAt = character.Location;

            if (locatedAt != null)
            {
                // We're on the atlas!

                float y = top + renderer.TextAscender - ((character.Height + character.MinY) * Text.FontSize);

                float scaleFactor = renderer.TextScaleFactor;

                screenRegion.Set(left + (character.LeftSideBearing * Text.FontSize), y, locatedAt.Width * scaleFactor, locatedAt.Height * scaleFactor);

                if (screenRegion.Overlaps(renderer.ClippingBoundary))
                {
                    // True if this character is visible.

                    // Ensure correct batch:
                    renderer.SetupBatch(this, null, locatedAt.Atlas);

                    MeshBlock block = Add(renderer);
                    block.SetColour(renderer.FontColour);
                    block.ApplyOutline();

                    // And clip our meshblock to fit within boundary:
                    block.ImageUV = null;
                    UVBlock uvs = block.SetClipped(renderer.ClippingBoundary, screenRegion, renderer, RenderData.computedStyle.ZIndex, locatedAt, block.TextUV);

                    if (uvs.Shared)
                    {
                        uvs = new UVBlock(uvs);
                    }

                    // Invert along X:
                    float temp = uvs.MinX;
                    uvs.MinX = uvs.MaxX;
                    uvs.MaxX = temp;

                    // Assign to the block:
                    block.TextUV = uvs;

                    block.Done(renderer.Transform);
                }
            }

            left += (character.AdvanceWidth * Text.FontSize) + Text.LetterSpacing;

            if (character.Charcode == (int)' ')
            {
                left += Text.WordSpacing;
            }
        }
Esempio n. 16
0
        /// <summary>Draws a character with x-inverted UV's. Used for rendering e.g. "1 < 2" in right-to-left.</summary>
        private void DrawInvertCharacter(int index, ref float left, float top, Renderman renderer, float zIndex, BoxRegion screenRegion)
        {
            Glyph character = Characters[index];

            if (character == null)
            {
                return;
            }

            if (Kerning != null)
            {
                left += Kerning[index] * FontSize;
            }

            if (character.Space)
            {
                left += SpaceSize + LetterSpacing;
                return;
            }

            float y = top + Ascender - ((character.Height + character.MinY) * FontSize);

            AtlasLocation locatedAt = character.Location;

            if (locatedAt == null)
            {
                // Not in font.
                return;
            }

            screenRegion.Set(left + (character.LeftSideBearing * FontSize), y, locatedAt.Width * ScaleFactor, locatedAt.Height * ScaleFactor);

            if (screenRegion.Overlaps(renderer.ClippingBoundary))
            {
                // True if this character is visible.

                // Ensure correct batch:
                SetupBatch(null, locatedAt.Atlas);

                MeshBlock block = Add();
                block.SetColour(FontColour);

                // And clip our meshblock to fit within boundary:
                block.ImageUV = null;
                UVBlock uvs = block.SetClipped(renderer.ClippingBoundary, screenRegion, renderer, zIndex, locatedAt, block.TextUV);

                if (uvs.Shared)
                {
                    uvs = new UVBlock(uvs);
                }

                // Invert along X:
                float temp = uvs.MinX;
                uvs.MinX = uvs.MaxX;
                uvs.MaxX = temp;

                // Assign to the block:
                block.TextUV = uvs;
            }

            left += (character.AdvanceWidth * FontSize) + LetterSpacing;
        }
Esempio n. 17
0
 public bool DrawToAtlas(TextureAtlas atlas, AtlasLocation location)
 {
     // Draw now:
     return(Rasterise(atlas.Pixels, atlas.Dimension, location.BottomLeftPixel(), true));
 }