|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.Shell.Interop;
namespace Microsoft.CodeAnalysis.ColorSchemes;
internal partial class ColorSchemeApplier
{
private static class RegistryItemConverter
{
private const uint FullyOpaqueAlpha = 0xFF000000;
private const uint RegistryVersion = 0x0B;
public static ImmutableArray<RegistryItem> Convert(ColorScheme scheme)
{
return scheme.Themes
.Select(ToRegistryItem)
.ToImmutableArray();
}
private static RegistryItem ToRegistryItem(ColorTheme theme)
{
var sectionName = $"Themes\\{theme.Guid:B}\\{theme.Category.Name}";
var data = ToData(theme);
return new RegistryItem(sectionName, data);
}
private static byte[] ToData(ColorTheme theme)
{
//|-------------Header----------------|--Categories...
//|-Byte Count|--Version--|CategoryCnt|--
//:ca,05,00,00,0b,00,00,00,01,00,00,00,--
// Initialize with a generous initial capacity.
var bytes = new MemoryStream(4096);
// Reserve space to write the total length.
WriteDWord(bytes, 0);
// Write the Version into the header.
WriteDWord(bytes, RegistryVersion);
// Write the category count into the header.
WriteDWord(bytes, 1);
WriteCategory(bytes, theme.Category);
// Write the data length into the space that we reserved.
bytes.Seek(0, SeekOrigin.Begin);
WriteDWord(bytes, (uint)bytes.Length);
return bytes.ToArray();
}
private static void WriteDWord(MemoryStream bytes, uint dword)
{
bytes.WriteByte((byte)dword);
bytes.WriteByte((byte)(dword >> 8));
bytes.WriteByte((byte)(dword >> 16));
bytes.WriteByte((byte)(dword >> 24));
}
private static void WriteCategory(MemoryStream bytes, ColorCategory category)
{
// |------------------------Category---------------------------|--Items...
// |----------------Category GUID------------------|-Item Count|--
// ,85,56,a0,75,a8,00,ed,4d,ba,e5,e7,a5,0b,fa,92,9a,2e,00,00,00,--
WriteGuid(bytes, category.Guid);
WriteDWord(bytes, (uint)category.Colors.Length);
foreach (var color in category.Colors)
{
WriteColor(bytes, color);
}
return;
static void WriteGuid(MemoryStream bytes, Guid guid)
{
bytes.Write(guid.ToByteArray(), 0, 16);
}
}
private static void WriteColor(MemoryStream bytes, ColorItem color)
{
// |-------------------------Item:Punctuation---------------------|
// |Name Length|-------------Name---------------|CT|CT|-ColorRef--|
// ,0b,00,00,00,70,75,6e,63,74,75,61,74,69,6f,6e,00,01,00,00,00,ff,
WriteDWord(bytes, (uint)color.Name.Length);
bytes.Write(Encoding.ASCII.GetBytes(color.Name), 0, color.Name.Length);
bytes.WriteByte((byte)color.BackgroundType);
if (color.Background.HasValue)
{
var background = color.Background.Value;
// Add back a fully opaque alpha value for RGB colors
if (color.BackgroundType == __VSCOLORTYPE.CT_RAW)
{
background |= FullyOpaqueAlpha;
}
WriteDWord(bytes, background);
}
bytes.WriteByte((byte)color.ForegroundType);
if (color.Foreground.HasValue)
{
var foreground = color.Foreground.Value;
// Add back a fully opaque alpha value for RGB colors
if (color.ForegroundType == __VSCOLORTYPE.CT_RAW)
{
foreground |= FullyOpaqueAlpha;
}
WriteDWord(bytes, foreground);
}
return;
}
}
}
|