void CreateNewLabelLayoutWrapped() { // // Stage 1 - Encode glyphs and calculate final dimensions // // Start a new layout glyphLayout.Clear(); // Set a local maxWidth that compensates for textScale int maxWidth = (int)(this.maxWidth / textScale); // First pass encodes ASCII and calculates final dimensions float width = 0; float greatestWidthFound = 0; int lastEndOfRowByte = 0; float spacing = font.GlyphSpacing; int[] codes = GetCodes(startCharacterIndex); List <int[]> rows = new List <int[]>(); List <float> rowWidth = new List <float>(); for (int i = 0; i < codes.Length; i++) { // Calculate total width float glyphWidth = font.GetGlyphWidth(codes[i], LocalScale, spacing); // If maxWidth is set, don't allow the label texture to exceed it if ((maxWidth <= 0) || ((width + glyphWidth + font.GlyphSpacing) <= maxWidth)) { width += glyphWidth; } else { int rowLength; if (wrapWords) { int j; for (j = i; j >= lastEndOfRowByte; j--) { glyphWidth = font.GetGlyphWidth(codes[j], LocalScale, spacing); if (j < i) // glyph i has not been added to width { width -= glyphWidth; if (width <= maxWidth && codes[j] == DaggerfallFont.SpaceCode) { break; } } } if (j > lastEndOfRowByte) // space found in row at position that is not exceeding maxWidth for all summed glyph's widths before this position { i = j; // set new processing position (j is the space position, i will be increased on next loop iteration to point to next chat after the space char) rowLength = j - lastEndOfRowByte; // set length from row start to position before space } else { rowLength = i - lastEndOfRowByte; } // compute width of text-wrapped line width = 0; for (int k = lastEndOfRowByte; k < j; k++) { if (k < j - 1 || (k == j - 1 && codes[k] != DaggerfallFont.SpaceCode)) // all expect last character if it is a space { glyphWidth = font.GetGlyphWidth(codes[k], LocalScale, spacing); width += glyphWidth; } } } else { rowLength = i - lastEndOfRowByte; } // The row of glyphs exceeded maxWidth. Add it to the list of rows and start // counting width again with the remainder of the ASCII bytes. List <int> content = new List <int>(codes).GetRange(lastEndOfRowByte, rowLength); if (content[content.Count - 1] == DaggerfallFont.SpaceCode) { content.RemoveAt(content.Count - 1); } int[] trimmed = content.ToArray(); rows.Add(trimmed); rowWidth.Add(width); // update greatest width found so far if (greatestWidthFound < width) { greatestWidthFound = width; } // reset width for next line width = 0; lastEndOfRowByte = i + 1; // position after space for next line, note: i will be increased on next loop iteration anyway - so no need to increase i } } if (lastEndOfRowByte > 0) { codes = new List <int>(codes).GetRange(lastEndOfRowByte, codes.Length - lastEndOfRowByte).ToArray(); } // also get width of last line width = 0; for (int i = 0; i < codes.Length; i++) { float glyphWidth = font.GetGlyphWidth(codes[i], LocalScale, spacing); width += glyphWidth; } // update greatest width found so far if (width <= maxWidth && greatestWidthFound < width) // width should always be <= maxWidth here { greatestWidthFound = width; } rows.Add(codes); rowWidth.Add(width); // Create virtual layout area totalWidth = maxWidth; totalHeight = (int)(rows.Count * font.GlyphHeight); numTextLines = rows.Count; // // Stage 2 - Add glyphs to layout // // Second pass adds glyphs to label texture float xpos = 0; float ypos = totalHeight - font.GlyphHeight; //foreach (byte[] row in rows) for (int r = 0; r < rows.Count; r++) { int[] row = rows[r]; float alignmentOffset; switch (horizontalTextAlignment) { default: case HorizontalTextAlignmentSetting.None: case HorizontalTextAlignmentSetting.Left: case HorizontalTextAlignmentSetting.Justify: alignmentOffset = 0.0f; break; case HorizontalTextAlignmentSetting.Center: alignmentOffset = (totalWidth - rowWidth[r]) * 0.5f; break; case HorizontalTextAlignmentSetting.Right: alignmentOffset = totalWidth - rowWidth[r]; break; } int numSpaces = 0; // needed to compute extra offset between words for HorizontalTextAlignmentSetting.Justify float extraSpaceToDistribute = 0; // needed to compute extra offset between words for HorizontalTextAlignmentSetting.Justify if (horizontalTextAlignment == HorizontalTextAlignmentSetting.Justify) { for (int i = 0; i < row.Length; i++) { if (row[i] == DaggerfallFont.SpaceCode) { numSpaces++; } } extraSpaceToDistribute = maxWidth - rowWidth[r]; } xpos = (int)alignmentOffset; for (int i = 0; i < row.Length; i++) { float glyphWidth = font.GetGlyphWidth(row[i], LocalScale); if (xpos + glyphWidth > totalWidth) { break; } if (row[i] == DaggerfallFont.SpaceCode) { if (numSpaces > 1) { int currentPortionExtraSpaceToDistribute = (int)Mathf.Round((float)extraSpaceToDistribute / (float)numSpaces); xpos += currentPortionExtraSpaceToDistribute; extraSpaceToDistribute -= currentPortionExtraSpaceToDistribute; numSpaces--; } else if (numSpaces == 1) { xpos += extraSpaceToDistribute; } } GlyphLayoutData glyphPos = new GlyphLayoutData() { x = xpos, y = totalHeight - font.GlyphHeight - ypos, code = row[i], width = glyphWidth, }; glyphLayout.Add(glyphPos); xpos += glyphWidth + font.GlyphSpacing; } ypos -= font.GlyphHeight; } Size = new Vector2(totalWidth * textScale, totalHeight * textScale); }
void CreateNewLabelLayoutSingleLine() { // // Stage 1 - Encode glyphs and calculate final dimensions // // Start a new layout glyphLayout.Clear(); // Set a local maxWidth that compensates for textScale int maxWidth = (int)(this.maxWidth / textScale); // First pass calculates final dimensions float width = 0; float spacing = font.GlyphSpacing; int[] codes = GetCodes(startCharacterIndex); for (int i = 0; i < codes.Length; i++) { width += font.GetGlyphWidth(codes[i], LocalScale, spacing); } // Trim width if (maxWidth > 0 && width > maxWidth) { width = maxWidth; } // Create virtual layout area totalWidth = width; totalHeight = font.GlyphHeight; numTextLines = 1; // // Stage 2 - Add glyphs to layout // // Determine horizontal alignment offset float alignmentOffset; switch (horizontalTextAlignment) { default: case HorizontalTextAlignmentSetting.None: case HorizontalTextAlignmentSetting.Left: case HorizontalTextAlignmentSetting.Justify: alignmentOffset = 0.0f; break; case HorizontalTextAlignmentSetting.Center: alignmentOffset = (totalWidth - width) * 0.5f; break; case HorizontalTextAlignmentSetting.Right: alignmentOffset = totalWidth - width; break; } // Second pass adds glyphs to layout float xpos = (int)alignmentOffset; for (int i = 0; i < codes.Length; i++) { float glyphWidth = font.GetGlyphWidth(codes[i], LocalScale); if (xpos + glyphWidth >= totalWidth) { break; } GlyphLayoutData glyphPos = new GlyphLayoutData() { x = xpos, y = 0, code = codes[i], width = glyphWidth, }; glyphLayout.Add(glyphPos); xpos += glyphWidth + spacing; } Size = new Vector2(totalWidth * textScale, totalHeight * textScale); }
void CreateNewLabelLayoutSingleLine() { // // Stage 1 - Encode glyphs and calculate final dimensions // // Use default UI font if none set if (font == null) { font = DaggerfallUI.DefaultFont; } // Start a new layout labelLayout = new LabelLayoutData(); List <GlyphLayoutData> glyphLayout = new List <GlyphLayoutData>(); // Set a local maxWidth that compensates for textScale int maxWidth = (int)(this.maxWidth / textScale); // First pass encodes ASCII and calculates final dimensions int width = 0; asciiBytes = Encoding.Convert(Encoding.UTF8, Encoding.GetEncoding("ISO-8859-1"), Encoding.Default.GetBytes(text)); for (int i = startCharacterIndex; i < asciiBytes.Length; i++) { // Invalid ASCII bytes are cast to a space character if (!font.HasGlyph(asciiBytes[i])) { asciiBytes[i] = DaggerfallFont.SpaceASCII; } // Calculate total width DaggerfallFont.GlyphInfo glyph = font.GetGlyph(asciiBytes[i]); width += glyph.width + font.GlyphSpacing; } // Trim width if (maxWidth > 0 && width > maxWidth) { width = maxWidth; } // Create virtual layout area totalWidth = width; totalHeight = (int)(font.GlyphHeight); numTextLines = 1; labelLayout.width = totalWidth; labelLayout.height = totalHeight; // // Stage 2 - Add glyph to layout // // Determine horizontal alignment offset float alignmentOffset; switch (horizontalTextAlignment) { default: case HorizontalTextAlignmentSetting.None: case HorizontalTextAlignmentSetting.Left: case HorizontalTextAlignmentSetting.Justify: alignmentOffset = 0.0f; break; case HorizontalTextAlignmentSetting.Center: alignmentOffset = (totalWidth - width) * 0.5f; break; case HorizontalTextAlignmentSetting.Right: alignmentOffset = totalWidth - width; break; } // Second pass adds glyphs to layout int xpos = (int)alignmentOffset; for (int i = startCharacterIndex; i < asciiBytes.Length; i++) { DaggerfallFont.GlyphInfo glyph = font.GetGlyph(asciiBytes[i]); if (xpos + glyph.width >= totalWidth) { break; } GlyphLayoutData glyphPos = new GlyphLayoutData() { x = xpos, y = 0, glyphRawAscii = asciiBytes[i], glyphWidth = glyph.width, }; glyphLayout.Add(glyphPos); xpos += glyph.width + font.GlyphSpacing; } labelLayout.glyphLayout = glyphLayout.ToArray(); this.Size = new Vector2(totalWidth * textScale, totalHeight * textScale); }