最近在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;
}

NinePatchChunk.java分析的更多相关文章

  1. java分析源码-ReentrantLock

    一.前言 在分析了 AbstractQueuedSynchronier 源码后,接着分析ReentrantLock源码,其实在 AbstractQueuedSynchronizer 的分析中,已经提到 ...

  2. JAVA分析html算法(JAVA网页蜘蛛算法)

    近来有些朋友在做蜘蛛算法,或者在网页上面做深度的数据挖掘.但是遇到复杂而繁琐的html页面大家都望而却步.因为很难获取到相应的数据. 最古老的办法的是尝试用正则表达式,估计那么繁琐的东西得不偿失,浪费 ...

  3. Java 分析工具汇总

    http://blog.csdn.net/fenglibing/article/details/6411999 jps  jps -mlvV jmap jmap -heap <pid>   ...

  4. hello.java分析

    如下图源码所示: 该段代码声明了一个entity实体类,该类有一个变量name,对该变量写了对应的get和set方法.类中还有一个空的构造方法hello(). @RequestScoped用于指定一个 ...

  5. Week4——Hello.java分析

    如下图源码所示: 该段代码声明了一个entity实体类,该类有一个变量name,对该变量写了对应的get和set方法.类中还有一个空的构造方法hello(). @RequestScoped用于指定一个 ...

  6. 启动入口Start.java分析

    框架的启动器在包:org.ofbiz.base.start 入口为:Start.java的main方法 Start.java启动器内容: 步骤 详情 入参校验 help/status/shutdown ...

  7. Intent.java分析

    代码位于frameworks/base/core/java/anroid/Content/Intent.java Intent是对要进行操作的一种抽象描述.用action抽象操作,用data(andr ...

  8. java分析工具arthas

    wget https://alibaba.github.io/arthas/arthas-boot.jar java -jar arthas-boot.jar --target-ip 0.0.0.0

  9. java 分析方法调用过程

    StackTraceElement[] s = new Exception().getStackTrace(); for(int i=0;i<s.length;i++) System.out.p ...

随机推荐

  1. 诊断:ORA-00376 & ORA-01110

    现象: Errors in file /path/of/diag/rdbms/prod/PROD/trace/PROD_ora_13447.trc: ORA-00376: 此时无法读取文件 61 OR ...

  2. 51nod 1021 石子归并 - 区间dp(经典)

    题目地址:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1021 经典区间dp,dp[i][j] 表示将从 i 到 j 堆 ...

  3. 81-Gator Oscillator,加多摆动指标.(2015.7.1)

    Gator Oscillator 加多摆动指标 Oscillator,加多摆动指标.(2015.7.1)" title="81-Gator Oscillator,加多摆动指标.(2 ...

  4. ICE CAVE(BFS搜索(模拟))

    Description You play a computer game. Your character stands on some level of a multilevel ice cave. ...

  5. Vue如何mock数据模拟Ajax请求

    我们在做一个项目时前期可能没有后端提供接口模拟数据,那么作为前端就需要自己写json文件模拟数据加载.网上往往参考的都是不全面的,比如get请求没问题但是post请求就报错了.在Vue中只需要vue- ...

  6. 立方体 反射 CubeMap

    立方体反射(CubeMap) 在虚拟环境中,我们需要模拟材质球反射周围的环境,立方体反射正是让材质球反射出天空盒的背景的方法之一. 原理 当我们观察物体时,物体表面足够光滑,再视线方向和物体相交的点上 ...

  7. 添物不花钱学JavaEE(基础篇)- Java

    Java Java是一面向对象语言 Write Once Run Anywhere Designed for easy Web/Internet applications, Mobile Widesp ...

  8. HDU-3790最短路径问题,第十遍终于过了~

    最短路径问题                                                                   Time Limit: 2000/1000 MS (J ...

  9. 【莫比乌斯反演+树状数组+分块求和】GCD Array

    https://www.bnuoj.com/v3/contest_show.php?cid=9149#problem/I [题意] 给定长度为l的一个数组,初始值为0:规定了两种操作: [思路] 找到 ...

  10. httpClient使用总结

    前记 最近有个需求,需要根据商品id获取商品详情: 首先想到的是在浏览器里输入url按回车就可以了:或者在linux中使用curl+url来发起一个http请求; 但如果是要在java程序中发出htt ...