Fixed rendering of 9-patch images in retina resolution
This commit is contained in:
Родитель
2b7a78e58e
Коммит
31083e058e
|
@ -143,5 +143,17 @@
|
|||
<EmbeddedResource Include="Tests\ninep-tt.9.png">
|
||||
<LogicalName>ninep-tt.9.png</LogicalName>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Tests\ninep-ss.9%402x.png">
|
||||
<LogicalName>ninep-ss.9@2x.png</LogicalName>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Tests\ninep-st.9%402x.png">
|
||||
<LogicalName>ninep-st.9@2x.png</LogicalName>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Tests\ninep-ts.9%402x.png">
|
||||
<LogicalName>ninep-ts.9@2x.png</LogicalName>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Tests\ninep-tt.9%402x.png">
|
||||
<LogicalName>ninep-tt.9@2x.png</LogicalName>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -270,5 +270,17 @@
|
|||
<EmbeddedResource Include="Tests\ninep-tt.9.png">
|
||||
<LogicalName>ninep-tt.9.png</LogicalName>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Tests\ninep-ss.9%402x.png">
|
||||
<LogicalName>ninep-ss.9@2x.png</LogicalName>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Tests\ninep-st.9%402x.png">
|
||||
<LogicalName>ninep-st.9@2x.png</LogicalName>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Tests\ninep-ts.9%402x.png">
|
||||
<LogicalName>ninep-ts.9@2x.png</LogicalName>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Tests\ninep-tt.9%402x.png">
|
||||
<LogicalName>ninep-tt.9@2x.png</LogicalName>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -52,11 +52,11 @@ namespace Xwt
|
|||
context.SetLineWidth (1);
|
||||
}
|
||||
|
||||
protected void CheckImage (string refImageName)
|
||||
protected void CheckImage (string refImageName, double scaleFactor = 1)
|
||||
{
|
||||
if (builder == null)
|
||||
return;
|
||||
var img = builder.ToBitmap ();
|
||||
var img = builder.ToBitmap (scaleFactor);
|
||||
builder.Dispose ();
|
||||
builder = null;
|
||||
|
||||
|
|
|
@ -189,6 +189,167 @@ namespace Xwt
|
|||
context.DrawImage (np, 0, 0);
|
||||
CheckImage ("NinePatchTileTileHigher.png");
|
||||
}
|
||||
|
||||
// 2x scale factor
|
||||
|
||||
[Test]
|
||||
public void NinePatchStretchStretchDefaultSize2x ()
|
||||
{
|
||||
var np = Image.FromResource ("ninep-ss.9.png");
|
||||
InitBlank ((int)np.Width, (int)np.Height);
|
||||
context.DrawImage (np, 0, 0);
|
||||
CheckImage ("NinePatchStretchStretchDefaultSize2x.png", 2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NinePatchStretchStretchWiderHigher2x ()
|
||||
{
|
||||
var np = Image.FromResource ("ninep-ss.9.png");
|
||||
np = np.WithSize (np.Width * 3, np.Height * 3);
|
||||
InitBlank ((int)np.Width, (int)np.Height);
|
||||
context.DrawImage (np, 0, 0);
|
||||
CheckImage ("NinePatchStretchStretchWiderHigher2x.png", 2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NinePatchStretchStretchWider2x ()
|
||||
{
|
||||
var np = Image.FromResource ("ninep-ss.9.png");
|
||||
np = np.WithSize (np.Width * 3, np.Height);
|
||||
InitBlank ((int)np.Width, (int)np.Height);
|
||||
context.DrawImage (np, 0, 0);
|
||||
CheckImage ("NinePatchStretchStretchWider2x.png", 2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NinePatchStretchStretchHigher2x ()
|
||||
{
|
||||
var np = Image.FromResource ("ninep-ss.9.png");
|
||||
np = np.WithSize (np.Width, np.Height * 3);
|
||||
InitBlank ((int)np.Width, (int)np.Height);
|
||||
context.DrawImage (np, 0, 0);
|
||||
CheckImage ("NinePatchStretchStretchHigher2x.png", 2);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void NinePatchStretchTileDefaultSize2x ()
|
||||
{
|
||||
var np = Image.FromResource ("ninep-st.9.png");
|
||||
InitBlank ((int)np.Width, (int)np.Height);
|
||||
context.DrawImage (np, 0, 0);
|
||||
CheckImage ("NinePatchStretchTileDefaultSize2x.png", 2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NinePatchStretchTileWiderHigher2x ()
|
||||
{
|
||||
var np = Image.FromResource ("ninep-st.9.png");
|
||||
np = np.WithSize (np.Width * 3, np.Height * 3);
|
||||
InitBlank ((int)np.Width, (int)np.Height);
|
||||
context.DrawImage (np, 0, 0);
|
||||
CheckImage ("NinePatchStretchTileWiderHigher2x.png", 2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NinePatchStretchTileWider2x ()
|
||||
{
|
||||
var np = Image.FromResource ("ninep-st.9.png");
|
||||
np = np.WithSize (np.Width * 3, np.Height);
|
||||
InitBlank ((int)np.Width, (int)np.Height);
|
||||
context.DrawImage (np, 0, 0);
|
||||
CheckImage ("NinePatchStretchTileWider2x.png", 2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NinePatchStretchTileHigher2x ()
|
||||
{
|
||||
var np = Image.FromResource ("ninep-st.9.png");
|
||||
np = np.WithSize (np.Width, np.Height * 3);
|
||||
InitBlank ((int)np.Width, (int)np.Height);
|
||||
context.DrawImage (np, 0, 0);
|
||||
CheckImage ("NinePatchStretchTileHigher2x.png", 2);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void NinePatchTileStretchDefaultSize2x ()
|
||||
{
|
||||
var np = Image.FromResource ("ninep-ts.9.png");
|
||||
InitBlank ((int)np.Width, (int)np.Height);
|
||||
context.DrawImage (np, 0, 0);
|
||||
CheckImage ("NinePatchTileStretchDefaultSize2x.png", 2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NinePatchTileStretchWiderHigher2x ()
|
||||
{
|
||||
var np = Image.FromResource ("ninep-ts.9.png");
|
||||
np = np.WithSize (np.Width * 3, np.Height * 3);
|
||||
InitBlank ((int)np.Width, (int)np.Height);
|
||||
context.DrawImage (np, 0, 0);
|
||||
CheckImage ("NinePatchTileStretchWiderHigher2x.png", 2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NinePatchTileStretchWider2x ()
|
||||
{
|
||||
var np = Image.FromResource ("ninep-ts.9.png");
|
||||
np = np.WithSize (np.Width * 3, np.Height);
|
||||
InitBlank ((int)np.Width, (int)np.Height);
|
||||
context.DrawImage (np, 0, 0);
|
||||
CheckImage ("NinePatchTileStretchWider2x.png", 2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NinePatchTileStretchHigher2x ()
|
||||
{
|
||||
var np = Image.FromResource ("ninep-ts.9.png");
|
||||
np = np.WithSize (np.Width, np.Height * 3);
|
||||
InitBlank ((int)np.Width, (int)np.Height);
|
||||
context.DrawImage (np, 0, 0);
|
||||
CheckImage ("NinePatchTileStretchHigher2x.png", 2);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void NinePatchTileTileDefaultSize2x ()
|
||||
{
|
||||
var np = Image.FromResource ("ninep-tt.9.png");
|
||||
InitBlank ((int)np.Width, (int)np.Height);
|
||||
context.DrawImage (np, 0, 0);
|
||||
CheckImage ("NinePatchTileTileDefaultSize2x.png", 2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NinePatchTileTileWiderHigher2x ()
|
||||
{
|
||||
var np = Image.FromResource ("ninep-tt.9.png");
|
||||
np = np.WithSize (np.Width * 3, np.Height * 3);
|
||||
InitBlank ((int)np.Width, (int)np.Height);
|
||||
context.DrawImage (np, 0, 0);
|
||||
CheckImage ("NinePatchTileTileWiderHigher2x.png", 2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NinePatchTileTileWider2x ()
|
||||
{
|
||||
var np = Image.FromResource ("ninep-tt.9.png");
|
||||
np = np.WithSize (np.Width * 3, np.Height);
|
||||
InitBlank ((int)np.Width, (int)np.Height);
|
||||
context.DrawImage (np, 0, 0);
|
||||
CheckImage ("NinePatchTileTileWider2x.png", 2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NinePatchTileTileHigher2x ()
|
||||
{
|
||||
var np = Image.FromResource ("ninep-tt.9.png");
|
||||
np = np.WithSize (np.Width, np.Height * 3);
|
||||
InitBlank ((int)np.Width, (int)np.Height);
|
||||
context.DrawImage (np, 0, 0);
|
||||
CheckImage ("NinePatchTileTileHigher2x.png", 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -99,8 +99,9 @@ namespace Xwt
|
|||
return null;
|
||||
}
|
||||
|
||||
public static void CheckImage (string refImageName, Image img)
|
||||
public static void CheckImage (string refImageName, Image im)
|
||||
{
|
||||
BitmapImage img = im as BitmapImage ?? im.ToBitmap ();
|
||||
Image coreRefImage = LoadReferenceImage (refImageName);
|
||||
|
||||
Image refImage = !RecheckAll ? LoadCustomReferenceImage (refImageName) : null;
|
||||
|
@ -109,8 +110,8 @@ namespace Xwt
|
|||
|
||||
if (refImage == null) {
|
||||
ImageFailures.Add (new FailedImageInfo () {
|
||||
TestImage = img,
|
||||
ReferenceImage = img,
|
||||
TestImage = img.WithSize (img.PixelWidth, img.PixelHeight),
|
||||
ReferenceImage = img.WithSize (img.PixelWidth, img.PixelHeight),
|
||||
Name = refImageName,
|
||||
TargetDir = ProjectReferenceImageDir
|
||||
});
|
||||
|
@ -135,8 +136,8 @@ namespace Xwt
|
|||
|
||||
if (!knownFailure) {
|
||||
ImageFailures.Add (new FailedImageInfo () {
|
||||
TestImage = img,
|
||||
ReferenceImage = refImage,
|
||||
TestImage = img.WithSize (img.PixelWidth, img.PixelHeight),
|
||||
ReferenceImage = refImage.WithSize (img.PixelWidth, img.PixelHeight),
|
||||
DiffImage = diff,
|
||||
Name = refImageName,
|
||||
TargetDir = ProjectCustomReferenceImageDir
|
||||
|
@ -149,13 +150,13 @@ namespace Xwt
|
|||
public static Image DiffImages (Image img1, Image img2)
|
||||
{
|
||||
bool foundDifference = false;
|
||||
var bmp1 = img1.ToBitmap ();
|
||||
var bmp2 = img2.ToBitmap ();
|
||||
var res = new ImageBuilder ((int)Math.Min (bmp1.Size.Width, bmp2.Size.Width), (int) Math.Min (bmp1.Size.Height, bmp2.Size.Height));
|
||||
var bmp1 = (img1 as BitmapImage) ?? img1.ToBitmap ();
|
||||
var bmp2 = (img2 as BitmapImage) ?? img2.ToBitmap ();
|
||||
var res = new ImageBuilder ((int)Math.Min (bmp1.PixelWidth, bmp2.PixelWidth), (int) Math.Min (bmp1.PixelHeight, bmp2.PixelHeight));
|
||||
var bmpr = res.ToBitmap ();
|
||||
res.Dispose ();
|
||||
for (int y=0; y<bmp1.Size.Height && y < bmp2.Size.Height; y++) {
|
||||
for (int x=0; x<bmp1.Size.Width && x<bmp2.Size.Width; x++) {
|
||||
for (int y=0; y<bmp1.PixelHeight && y < bmp2.PixelHeight; y++) {
|
||||
for (int x=0; x<bmp1.PixelWidth && x<bmp2.PixelWidth; x++) {
|
||||
var p1 = bmp1.GetPixel (x, y);
|
||||
var p2 = bmp2.GetPixel (x, y);
|
||||
var col = Colors.White;
|
||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 2.2 KiB |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 2.2 KiB |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 2.2 KiB |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 2.2 KiB |
|
@ -344,8 +344,9 @@ namespace Xwt.GtkBackend
|
|||
using (var ctx = new Cairo.Context (sf)) {
|
||||
ImageDescription idesc = new ImageDescription () {
|
||||
Alpha = 1,
|
||||
Size = new Size (width * scaleFactor, height * scaleFactor)
|
||||
Size = new Size (width, height)
|
||||
};
|
||||
ctx.Scale (scaleFactor, scaleFactor);
|
||||
Draw (actx, ctx, scaleFactor, 0, 0, idesc);
|
||||
var f = new ImageFrame (ImageBuilderBackend.CreatePixbuf (sf), Math.Max((int)width,1), Math.Max((int)height,1), true);
|
||||
AddFrame (f);
|
||||
|
|
|
@ -43,6 +43,7 @@ namespace Xwt.Mac
|
|||
public CGAffineTransform? InverseViewTransform;
|
||||
public Stack<ContextStatus> StatusStack = new Stack<ContextStatus> ();
|
||||
public ContextStatus CurrentStatus = new ContextStatus ();
|
||||
public double ScaleFactor = 1;
|
||||
}
|
||||
|
||||
class ContextStatus
|
||||
|
@ -56,7 +57,8 @@ namespace Xwt.Mac
|
|||
|
||||
public override double GetScaleFactor (object backend)
|
||||
{
|
||||
return 1;
|
||||
var ct = (CGContextBackend) backend;
|
||||
return ct.ScaleFactor;
|
||||
}
|
||||
|
||||
public override void Save (object backend)
|
||||
|
|
|
@ -129,12 +129,13 @@ namespace Xwt.Mac
|
|||
|
||||
var bmp = new CGBitmapContext (IntPtr.Zero, pixelWidth, pixelHeight, 8, bytesPerRow, Util.DeviceRGBColorSpace, flags);
|
||||
bmp.TranslateCTM (0, pixelHeight);
|
||||
bmp.ScaleCTM (1, -1);
|
||||
bmp.ScaleCTM ((float)scaleFactor, (float)-scaleFactor);
|
||||
|
||||
var ctx = new CGContextBackend {
|
||||
Context = bmp,
|
||||
Size = new SizeF (pixelWidth, pixelHeight),
|
||||
InverseViewTransform = bmp.GetCTM ().Invert ()
|
||||
Size = new SizeF ((float)width, (float)height),
|
||||
InverseViewTransform = bmp.GetCTM ().Invert (),
|
||||
ScaleFactor = scaleFactor
|
||||
};
|
||||
|
||||
var ci = (CustomImage)handle;
|
||||
|
@ -146,6 +147,7 @@ namespace Xwt.Mac
|
|||
var im = new NSImage ();
|
||||
im.AddRepresentation (imageRep);
|
||||
im.Size = new SizeF ((float)width, (float)height);
|
||||
bmp.Dispose ();
|
||||
return im;
|
||||
}
|
||||
else {
|
||||
|
@ -192,7 +194,11 @@ namespace Xwt.Mac
|
|||
public override Size GetSize (object handle)
|
||||
{
|
||||
NSImage img = (NSImage)handle;
|
||||
return new Size ((int)img.Size.Width, (int)img.Size.Height);
|
||||
NSBitmapImageRep bitmap = img.Representations ().OfType<NSBitmapImageRep> ().FirstOrDefault ();
|
||||
if (bitmap != null)
|
||||
return new Size (bitmap.PixelsWide, bitmap.PixelsHigh);
|
||||
else
|
||||
return new Size ((int)img.Size.Width, (int)img.Size.Height);
|
||||
}
|
||||
|
||||
public override object CopyBitmap (object handle)
|
||||
|
|
|
@ -252,8 +252,8 @@ namespace Xwt.Drawing
|
|||
if (i == -1)
|
||||
scaleFactor = 1;
|
||||
else {
|
||||
int j = fi.Item1.IndexOf ('.', ++i);
|
||||
if (!double.TryParse (fi.Item1.Substring (i + 1, j - i), out scaleFactor)) {
|
||||
int j = fi.Item1.IndexOf ('x', ++i);
|
||||
if (!double.TryParse (fi.Item1.Substring (i, j - i), out scaleFactor)) {
|
||||
toolkit.ImageBackendHandler.Dispose (fi.Item2);
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -138,8 +138,8 @@ namespace Xwt.Drawing
|
|||
var frame = GetFrame (ctx.ScaleFactor);
|
||||
var fixedWidth = frame.Bitmap.Width - 2 - frame.StretchableWidth;
|
||||
var fixedHeight = frame.Bitmap.Height - 2 - frame.StretchableHeight;
|
||||
double totalVariableWidth = bounds.Width - fixedWidth;
|
||||
double totalVariableHeight = bounds.Height - fixedHeight;
|
||||
double totalVariableWidth = bounds.Width - fixedWidth / frame.ScaleFactor;
|
||||
double totalVariableHeight = bounds.Height - fixedHeight / frame.ScaleFactor;
|
||||
double remainingVariableHeight = totalVariableHeight;
|
||||
|
||||
double y = bounds.Y, yb = 1;
|
||||
|
@ -173,34 +173,30 @@ namespace Xwt.Drawing
|
|||
var t = GetTile (frame, tileIndex, sourceRegion);
|
||||
ctx.DrawImage (t, targetRegion);
|
||||
} else {
|
||||
double scaleX = 1;
|
||||
double scaleY = 1;
|
||||
double pw = hs.Size / frame.ScaleFactor;
|
||||
double ph = vs.Size / frame.ScaleFactor;
|
||||
if (hs.Mode == RenderMode.Stretch) {
|
||||
scaleX = sw / hs.Size;
|
||||
targetRegion.Width = hs.Size;
|
||||
pw = targetRegion.Width;
|
||||
}
|
||||
if (vs.Mode == RenderMode.Stretch) {
|
||||
scaleY = sh / vs.Size;
|
||||
targetRegion.Height = vs.Size;
|
||||
ph = targetRegion.Height;
|
||||
}
|
||||
|
||||
ctx.Save ();
|
||||
ctx.Translate (targetRegion.Location);
|
||||
if (scaleX != 1 || scaleY != 1)
|
||||
ctx.Scale (scaleX, scaleY);
|
||||
targetRegion.Location = Point.Zero;
|
||||
ctx.Pattern = new ImagePattern (GetTile (frame, tileIndex, sourceRegion));
|
||||
ctx.Pattern = new ImagePattern (GetTile (frame, tileIndex, sourceRegion).WithSize (pw, ph));
|
||||
ctx.NewPath ();
|
||||
ctx.Rectangle (targetRegion);
|
||||
ctx.Fill ();
|
||||
ctx.Restore ();
|
||||
}
|
||||
x += sw / frame.ScaleFactor;
|
||||
x += sw;
|
||||
xb += hs.Size;
|
||||
tileIndex++;
|
||||
}
|
||||
yb += vs.Size;
|
||||
y += sh / frame.ScaleFactor;
|
||||
y += sh;
|
||||
}
|
||||
ctx.Restore ();
|
||||
}
|
||||
|
@ -215,7 +211,7 @@ namespace Xwt.Drawing
|
|||
return sw;
|
||||
}
|
||||
else {
|
||||
return sec.Size;
|
||||
return sec.Size / frame.ScaleFactor;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -234,8 +230,10 @@ namespace Xwt.Drawing
|
|||
|
||||
protected sealed override Size GetDefaultSize ()
|
||||
{
|
||||
var frame = frames [0];
|
||||
return new Size (frame.Bitmap.Width - 2, frame.Bitmap.Height - 2);
|
||||
var frame = GetFrame (1);
|
||||
if (frame == null)
|
||||
frame = frames [0];
|
||||
return new Size ((frame.Bitmap.Width - 2) / frame.ScaleFactor, (frame.Bitmap.Height - 2) / frame.ScaleFactor);
|
||||
}
|
||||
|
||||
public WidgetSpacing Padding { get; private set; }
|
||||
|
|
Загрузка…
Ссылка в новой задаче