Files
s&box team 71f266059a Open source release
This commit imports the C# engine code and game files, excluding C++ source code.

[Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
2025-11-24 09:05:18 +00:00

235 lines
6.7 KiB
C#

// RichTextKit
// Copyright © 2019-2020 Topten Software. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may
// not use this product except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Topten.RichTextKit.Utils;
namespace Topten.RichTextKit
{
/// <summary>
/// Represents a unicode string and all associated attributes
/// for each character required for the Bidi algorithm
/// </summary>
class BidiData
{
/// <summary>
/// Construct a new empty BidiData
/// </summary>
public BidiData()
{
_types = new Buffer<Directionality>();
_pairedBracketTypes = new Buffer<PairedBracketType>();
_pairedBracketValues = new Buffer<int>();
}
List<int> _paragraphPositions = new List<int>();
sbyte _paragraphEmbeddingLevel;
public sbyte ParagraphEmbeddingLevel => _paragraphEmbeddingLevel;
bool _hasBrackets;
public bool HasBrackets => _hasBrackets;
bool _hasEmbeddings;
public bool HasEmbeddings => _hasEmbeddings;
bool _hasIsolates;
public bool HasIsolates => _hasIsolates;
/// <summary>
/// Initialize with an array of Unicode code points
/// </summary>
/// <param name="codePoints">The unicode code points to be processed</param>
/// <param name="paragraphEmbeddingLevel">The paragraph embedding level</param>
public void Init( Slice<int> codePoints, sbyte paragraphEmbeddingLevel )
{
// Set working buffer sizes
_types.Length = codePoints.Length;
_pairedBracketTypes.Length = codePoints.Length;
_pairedBracketValues.Length = codePoints.Length;
_paragraphPositions.Clear();
_paragraphEmbeddingLevel = paragraphEmbeddingLevel;
// Resolve the directionality, paired bracket type and paired bracket values for
// all code points
_hasBrackets = false;
_hasEmbeddings = false;
_hasIsolates = false;
for ( int i = 0; i < codePoints.Length; i++ )
{
var bidiData = UnicodeClasses.BidiData( codePoints[i] );
// Look up directionality
var dir = (Directionality)(bidiData >> 24);
_types[i] = dir;
switch ( dir )
{
case Directionality.LRE:
case Directionality.LRO:
case Directionality.RLE:
case Directionality.RLO:
case Directionality.PDF:
_hasEmbeddings = true;
break;
case Directionality.LRI:
case Directionality.RLI:
case Directionality.FSI:
case Directionality.PDI:
_hasIsolates = true;
break;
}
// Lookup paired bracket types
var pbt = (PairedBracketType)((bidiData >> 16) & 0xFF);
_pairedBracketTypes[i] = pbt;
switch ( pbt )
{
case PairedBracketType.o:
_pairedBracketValues[i] = MapCanon( (int)(bidiData & 0xFFFF) );
_hasBrackets = true;
break;
case PairedBracketType.c:
_pairedBracketValues[i] = MapCanon( codePoints[i] );
_hasBrackets = true;
break;
}
/*
if (_types[i] == RichTextKit.Directionality.B)
{
_types[i] = (Directionality)Directionality.WS;
_paragraphPositions.Add(i);
}
*/
}
// Create slices on work buffers
Types = _types.AsSlice();
PairedBracketTypes = _pairedBracketTypes.AsSlice();
PairedBracketValues = _pairedBracketValues.AsSlice();
}
/// <summary>
/// Map bracket types 0x3008 and 0x3009 to their canonical equivalents
/// </summary>
/// <param name="codePoint">The code point to be mapped</param>
/// <returns>The mapped canonical code point, or the passed code point</returns>
static int MapCanon( int codePoint )
{
if ( codePoint == 0x3008 )
return 0x2329;
if ( codePoint == 0x3009 )
return 0x232A;
else
return codePoint;
}
/// <summary>
/// Get the length of the data held by the BidiData
/// </summary>
public int Length => _types.Length;
Buffer<Directionality> _types;
Buffer<PairedBracketType> _pairedBracketTypes;
Buffer<int> _pairedBracketValues;
Buffer<Directionality> _savedTypes;
Buffer<PairedBracketType> _savedPairedBracketTypes;
/// <summary>
/// Save the Types and PairedBracketTypes of this bididata
/// </summary>
/// <remarks>
/// This is used when processing embedded style runs with
/// directionality overrides. TextBlock saves the data,
/// overrides the style runs to neutral, processes the bidi
/// data for the entire paragraph and then restores this data
/// before processing the embedded runs.
/// </remarks>
public void SaveTypes()
{
// Make sure we have a buffer
if ( _savedTypes == null )
{
_savedTypes = new Buffer<Directionality>();
_savedPairedBracketTypes = new Buffer<PairedBracketType>();
}
// Capture the types data
_savedTypes.Clear();
_savedTypes.Add( _types.AsSlice() );
_savedPairedBracketTypes.Clear();
_savedPairedBracketTypes.Add( _pairedBracketTypes.AsSlice() );
}
/// <summary>
/// Restore the data saved by SaveTypes
/// </summary>
public void RestoreTypes()
{
_types.Clear();
_types.Add( _savedTypes.AsSlice() );
_pairedBracketTypes.Clear();
_pairedBracketTypes.Add( _savedPairedBracketTypes.AsSlice() );
}
/// <summary>
/// The directionality of each code point
/// </summary>
public Slice<Directionality> Types;
/// <summary>
/// The paired bracket type for each code point
/// </summary>
public Slice<PairedBracketType> PairedBracketTypes;
/// <summary>
/// The paired bracket value for code code point
/// </summary>
/// <remarks>
/// The paired bracket values are the code points
/// of each character where the opening code point
/// is replaced with the closing code point for easier
/// matching. Also, bracket code points are mapped
/// to their canonical equivalents
/// </remarks>
public Slice<int> PairedBracketValues;
public Buffer<sbyte> _tempLevelBuffer;
/// <summary>
/// Gets a temporary level buffer. Used by TextBlock when
/// resolving style runs with different directionality.
/// </summary>
/// <param name="length">Length of the required buffer</param>
/// <returns>An uninitialized level buffer</returns>
public Slice<sbyte> GetTempLevelBuffer( int length )
{
if ( _tempLevelBuffer == null )
_tempLevelBuffer = new Buffer<sbyte>();
_tempLevelBuffer.Clear();
return _tempLevelBuffer.Add( length, false );
}
}
}