/// <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; } }
/// <summary>Sets the UV and image on this block to that of the solid colour pixel.</summary> public void SetSolidColourUV() { // Set the UVs - solid colour is always at y>1: ImageUV = null; TextUV = null; }
/// <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; } }
/// <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); }
/// <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; }