zoukankan      html  css  js  c++  java
  • NinePatchChunk.java分析

    最近在Swing中使用.9图片,用到了NinePatchChunk.java文件,但是发现有时会出现无法完美展示的情况,决定修复一下这个问题,顺便研究一些.9的绘制过程

    通过分析发现draw函数先是计算出固定宽高大小,再计算出拉升区域大小,最后遍历固定大小和拉伸大小的矩形,进行拉升的覆盖。

    在分析的时候发现,我所遇到的bug是通过计算固定高得到拉伸高度时,如果有一边被填满就无法计算准确这个值引起的。

    这里:

            int remainderHorizontal = 0;
            int remainderVertical = 0;
    
            if (mFixed.size() > 0) {
                int start = mFixed.get(0).y;
                for (Rectangle rect : mFixed) {
                    if (rect.y > start) {
                        endRow = true;
                        measuredWidth = true;
                    }
                    if (!measuredWidth) {
                        remainderHorizontal += rect.width;
                    }
                    if (endRow) {
                        remainderVertical += rect.height;
                        endRow = false;
                        start = rect.y;
                    }
                }
            }
    
            data.mRemainderHorizontal = scaledWidth - remainderHorizontal;
            data.mRemainderVertical = scaledHeight - remainderVertical;

    解决方法之一就是不使用填满边的.9图。当然也可以修改代码来解决。

    绘制的代码:

        private void draw(BufferedImage image, Graphics2D graphics2D, int x, int y, int scaledWidth,
                int scaledHeight) {
            if (scaledWidth <= 1 || scaledHeight <= 1) {
                return;
            }
    
            Graphics2D g = (Graphics2D)graphics2D.create();
            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                    RenderingHints.VALUE_INTERPOLATION_BILINEAR);
    
            try {
                if (mPatches.size() == 0) {
                    g.drawImage(image, x, y, scaledWidth, scaledHeight, null);
                    return;
                }
    
                g.translate(x, y);
                x = y = 0;
    
                DrawingData data = computePatches(scaledWidth, scaledHeight);
    
                int fixedIndex = 0;
                int horizontalIndex = 0;
                int verticalIndex = 0;
                int patchIndex = 0;
    
                boolean hStretch;
                boolean vStretch;
    
                float vWeightSum = 1.0f;
                float vRemainder = data.mRemainderVertical;
    
                vStretch = mVerticalStartWithPatch;
                while (y < scaledHeight - 1) {
                    hStretch = mHorizontalStartWithPatch;
    
                    int height = 0;
                    float vExtra = 0.0f;
    
                    float hWeightSum = 1.0f;
                    float hRemainder = data.mRemainderHorizontal;
    
                    while (x < scaledWidth - 1) {
                        Rectangle r;
                        if (!vStretch) {
                            if (hStretch) {
                                r = mHorizontalPatches.get(horizontalIndex++);
                                float extra = r.width / data.mHorizontalPatchesSum;
                                int width = (int) (extra * hRemainder / hWeightSum);
                                hWeightSum -= extra;
                                hRemainder -= width;
                                g.drawImage(image, x, y, x + width, y + r.height, r.x, r.y,
                                        r.x + r.width, r.y + r.height, null);
                                x += width;
                            } else {
                                r = mFixed.get(fixedIndex++);
                                g.drawImage(image, x, y, x + r.width, y + r.height, r.x, r.y,
                                        r.x + r.width, r.y + r.height, null);
                                x += r.width;
                            }
                            height = r.height;
                        } else {
                            if (hStretch) {
                                r = mPatches.get(patchIndex++);
                                vExtra = r.height / data.mVerticalPatchesSum;
                                height = (int) (vExtra * vRemainder / vWeightSum);
                                float extra = r.width / data.mHorizontalPatchesSum;
                                int width = (int) (extra * hRemainder / hWeightSum);
                                hWeightSum -= extra;
                                hRemainder -= width;
                                g.drawImage(image, x, y, x + width, y + height, r.x, r.y,
                                        r.x + r.width, r.y + r.height, null);
                                x += width;
                            } else {
                                r = mVerticalPatches.get(verticalIndex++);
                                vExtra = r.height / data.mVerticalPatchesSum;
                                height = (int) (vExtra * vRemainder / vWeightSum);
                                g.drawImage(image, x, y, x + r.width, y + height, r.x, r.y,
                                        r.x + r.width, r.y + r.height, null);
                                x += r.width;
                            }
    
                        }
                        hStretch = !hStretch;
                    }
                    x = 0;
                    y += height;
                    if (vStretch) {
                        vWeightSum -= vExtra;
                        vRemainder -= height;
                    }
                    vStretch = !vStretch;
                }
    
            } finally {
                g.dispose();
            }
        }

    计算patch长度和固定长度的remainder的代码

        private DrawingData computePatches(int scaledWidth, int scaledHeight) {
            DrawingData data = new DrawingData();
            boolean measuredWidth = false;
            boolean endRow = true;
    
            int remainderHorizontal = 0;
            int remainderVertical = 0;
    
            if (mFixed.size() > 0) {
                int start = mFixed.get(0).y;
                for (Rectangle rect : mFixed) {
                    if (rect.y > start) {
                        endRow = true;
                        measuredWidth = true;
                    }
                    if (!measuredWidth) {
                        remainderHorizontal += rect.width;
                    }
                    if (endRow) {
                        remainderVertical += rect.height;
                        endRow = false;
                        start = rect.y;
                    }
                }
            }
    
            data.mRemainderHorizontal = scaledWidth - remainderHorizontal;
            data.mRemainderVertical = scaledHeight - remainderVertical;
    
            data.mHorizontalPatchesSum = 0;
            if (mHorizontalPatches.size() > 0) {
                int start = -1;
                for (Rectangle rect : mHorizontalPatches) {
                    if (rect.x > start) {
                        data.mHorizontalPatchesSum += rect.width;
                        start = rect.x;
                    }
                }
            } else {
                int start = -1;
                for (Rectangle rect : mPatches) {
                    if (rect.x > start) {
                        data.mHorizontalPatchesSum += rect.width;
                        start = rect.x;
                    }
                }
            }
    
            data.mVerticalPatchesSum = 0;
            if (mVerticalPatches.size() > 0) {
                int start = -1;
                for (Rectangle rect : mVerticalPatches) {
                    if (rect.y > start) {
                        data.mVerticalPatchesSum += rect.height;
                        start = rect.y;
                    }
                }
            } else {
                int start = -1;
                for (Rectangle rect : mPatches) {
                    if (rect.y > start) {
                        data.mVerticalPatchesSum += rect.height;
                        start = rect.y;
                    }
                }
            }
    
            return data;
        }
  • 相关阅读:
    引用 Geoprocessing调用ArcToolBox工具使用总结
    MySQL权限改观何时生效
    Ubuntu下安装*.bin挨次
    创立初始的MySQL权限
    MySQL的日期和光阴范例
    MySQL存取节制, 阶段1:连接证明
    让Linux操作零碎可以Mount NTFS分区
    Citrix进级XenDesktop桌面虚拟化产物
    如何在两台MySQL数据库间完成同步
    MySQL的数字
  • 原文地址:https://www.cnblogs.com/TLightSky/p/3479961.html
Copyright © 2011-2022 走看看