alternetsoft / AlternetUI

MIT License
22 stars 2 forks source link

NinePatch drawing? #115

Closed Shadowblitz16 closed 5 months ago

Shadowblitz16 commented 6 months ago

Can we have support for nine slice drawing with both stretch and tile modes?

graphics.DrawImageSliced(image, srcRect, destRect, patchRect, unitType, bool tileX, bool tileY)

I currently have this but it's broken.

    public void Draw        (Graphics graphics, RectI dst, RectI src)
    {
        dst = new RectI
        (
            (int)(DivX == 0 ? 0 : dst.X / DivX),
            (int)(DivY == 0 ? 0 : dst.Y / DivY),
            dst.Width ,
            dst.Height
        );

        //calculate sizes for each slice to cut from the original image
        int leftX               = src.Left;
        int rightX              = src.Right - (int)PatchRight;
        int centerX             = src.Left  + (int)PatchLeft;

        int topY                = src.Top;
        int bottomY             = src.Bottom - (int)PatchBottom;
        int centerY             = src.Top    + (int)PatchTop;

        int topHeight           = (int)PatchTop;
        int bottomHeight        = (int)PatchBottom;
        int centerHeight        = src.Height - (int)(PatchTop  + PatchBottom);

        int leftWidth           = (int)PatchLeft;
        int rightWidth          = (int)PatchRight;
        int centerWidth         = src.Width  - (int)(PatchLeft + PatchRight);

        //declare the bounds for each slice using the values above
        RectI topLeftSrc        = new RectI(leftX, topY, leftWidth, topHeight);
        RectI topCenterSrc      = new RectI(centerX, topY, centerWidth, topHeight);
        RectI topRightSrc       = new RectI(rightX, topY, rightWidth, topHeight);

        RectI bottomLeftSrc     = new RectI(leftX, bottomY, leftWidth, bottomHeight);
        RectI bottomCenterSrc   = new RectI(centerX, bottomY, centerWidth, bottomHeight);
        RectI bottomRightSrc    = new RectI(rightX, bottomY, rightWidth, bottomHeight);

        RectI centerLeftSrc     = new RectI(leftX, centerY, leftWidth, centerHeight);
        RectI centerCenterSrc   = new RectI(centerX, centerY, centerWidth, centerHeight);
        RectI centerRightSrc    = new RectI(rightX, centerY, rightWidth, centerHeight);

        //calculate sizes for each slice to be drawn to the screen

        //x positions for left, right and center slices
        leftX                   = dst.Left;
        rightX                  = dst.Right - (int)PatchRight;
        centerX                 = dst.Left  + (int)PatchLeft;

        //y positions for top, bottom and center slices
        topY                    = dst.Top;
        bottomY                 = dst.Bottom - (int)PatchBottom;
        centerY                 = dst.Top    + (int)PatchTop;

        //heights for left, right and center slices
        topHeight               = (int)PatchTop;
        bottomHeight            = (int)PatchBottom;
        centerHeight            = dst.Height - (int)(PatchTop  + PatchBottom);

        //widths for top, bottom and center slices
        leftWidth               = (int)PatchLeft;
        rightWidth              = (int)PatchRight;
        centerWidth             = dst.Width - (int)(PatchLeft + PatchRight);

        //declare the bounds for each slice using the values above
        RectI topLeftDest       = new RectI(leftX, topY, leftWidth, topHeight);
        RectI topCenterDest     = new RectI(centerX, topY, centerWidth, topHeight);
        RectI topRightDest      = new RectI(rightX, topY, rightWidth, topHeight);

        RectI bottomLeftDest    = new RectI(leftX, bottomY, leftWidth, bottomHeight);
        RectI bottomCenterDest  = new RectI(centerX, bottomY, centerWidth, bottomHeight);
        RectI bottomRightDest   = new RectI(rightX, bottomY, rightWidth, bottomHeight);

        RectI centerLeftDest    = new RectI(leftX, centerY, leftWidth, centerHeight);
        RectI centerCenterDest  = new RectI(centerX, centerY, centerWidth, centerHeight);
        RectI centerRightDest   = new RectI(rightX, centerY, rightWidth, centerHeight);

        //draw each slice to the screen
        if (topLeftDest.Width > 0 && topLeftDest.Height > 0 && topLeftSrc.Width > 0 && topLeftSrc.Height > 0)
            graphics.DrawImage(_internal, topLeftDest, topLeftSrc, GraphicsUnit.Pixel);

        if (topCenterDest.Width > 0 && topCenterDest.Height > 0 && topCenterSrc.Width > 0 && topCenterSrc.Height > 0)
            graphics.DrawImage(_internal, topCenterDest, topCenterSrc, GraphicsUnit.Pixel);

        if (topRightDest.Width > 0 && topRightDest.Height  > 0 && topRightSrc.Width > 0 && topRightSrc.Height > 0)
            graphics.DrawImage(_internal, topRightDest, topRightSrc, GraphicsUnit.Pixel);

        if (bottomLeftDest.Width > 0 && bottomLeftDest.Height  > 0 && bottomLeftSrc.Width > 0 && bottomLeftSrc.Height > 0)
            graphics.DrawImage(_internal, bottomLeftDest, bottomLeftSrc, GraphicsUnit.Pixel);

        if (bottomCenterDest.Width > 0 && bottomCenterDest.Height > 0 && bottomCenterSrc.Width > 0 && bottomCenterSrc.Height > 0)
            graphics.DrawImage(_internal, bottomCenterDest, bottomCenterSrc, GraphicsUnit.Pixel);

        if (bottomRightDest.Width > 0 && bottomRightDest.Height  > 0 && bottomRightSrc.Width > 0 && bottomRightSrc.Height > 0)
            graphics.DrawImage(_internal, bottomRightDest, bottomRightSrc, GraphicsUnit.Pixel);

        if (centerLeftDest.Width > 0 && centerLeftDest.Height  > 0 && centerLeftSrc.Width > 0 && centerLeftSrc.Height > 0)
            graphics.DrawImage(_internal, centerLeftDest, centerLeftSrc, GraphicsUnit.Pixel);

        if (centerCenterDest.Width > 0 && centerCenterDest.Height  > 0 && centerCenterSrc.Width > 0 && centerCenterSrc.Height > 0)
            graphics.DrawImage(_internal, centerCenterDest, centerCenterSrc, GraphicsUnit.Pixel);

        if (centerRightDest.Width > 0 && centerRightDest.Height  > 0 && centerRightSrc.Width > 0 && centerRightSrc.Height > 0)
            graphics.DrawImage(_internal, centerRightDest, centerRightSrc, GraphicsUnit.Pixel);
    }

maybe a implimenting a TextureBrush with tiled mode would make implementing this easier

generalloki commented 6 months ago

Please provide detailed explanation on what this method should do with parameters description. I am not sure I completely understand

Shadowblitz16 commented 6 months ago

@generalloki this is a nine patch image

basicly src would be a image sub rectangle, dst would be where it would be drawn and the patch rectangle would define the middle slice out of the src rectangle

generalloki commented 6 months ago

Now I understand. So this could be useful for backgrounds with round corners. Do you have ready images that are freeware and could be used for testing/demo purposes for this method? Also I have added TextureBrush issue as #116.

Also we have in Graphics:

RoundedRectangle(Pen pen, Brush brush, RectD rectangle, double cornerRadius)
Shadowblitz16 commented 6 months ago

panel

here is a image. I made it so you can test the following...

generalloki commented 6 months ago

Thanks I will use it in demo. I also found button image generator https://www.clickminded.com/button-generator/ and generated another sample image for the demo

image

generalloki commented 5 months ago

I added DrawingUtils.DrawSlicedImage. Example is in AlternetUI\Source\Samples\ControlsSample\InternalSamples\NinePatchDrawing\ TextureBrush is used to fill expanded space.

Shadowblitz16 commented 5 months ago

I added DrawingUtils.DrawSlicedImage. Example is in AlternetUI\Source\Samples\ControlsSample\InternalSamples\NinePatchDrawing TextureBrush is used to fill expanded space.

Is this a extension method for Alternet.Drawing.Graphics?

generalloki commented 5 months ago

DrawSlicedImage is static method of DrawingUtils. Not an extension method.

Shadowblitz16 commented 5 months ago

DrawSlicedImage is static method of DrawingUtils. Not an extension method.

Can you make it a extension method?

Also you might want to call it DrawImageSliced to be consistent with DrawImageUnscaled

generalloki commented 5 months ago

Renamed to DrawImageSliced and made an extension method to Graphics