AGG-SVG学习笔记 [2015-07-07]

河南洛阳 祝小鹰 2015-07-07

接触AGG一年多,积累了一些心得体会。现在贴出来与大家分享。

注1:学习笔记按记录时间的逆序排列。
注2:当初学习AGG的目的是为了绘制SVG图形文件,因此夹杂了一些SVG的内容。
注3:早期的笔记由于刚接触AGG,可能存在一些错误。

例程和库文件下载:http://pan.baidu.com/s/1o6OhqMQ


-----------------------------------------------------------------------
关于SVG中<linearGradinet>、<radialGradient>的属性xlink:href的补充说明:

- 只有在不包含<stop>子元素的情况下,才“继承”引用元素的<stop>子元素。

- 如果引用的url不存在,则忽略xlink:href属性。

- 允许间接引用,例如lg3引用lg2,而lg2引用lg1。

- <linearGradinet>可引用<radialGradient>,反之亦可。


-----------------------------------------------------------------------
AGG的marker locator(vcgen_markers_term)在处理分段线段时,每一个子线段都会生成一组起点和终点的定位信息。也就是说,每一个子线段的起点和终点都将绘制标记点。但是SVG仅在第一个起点和最后一个终点处绘制标记点。

因此为svg_viewer编写了一个类模板svg_markers_term,用于将AGG的marker locator转换为SVG规范。转换后,只保留第一个起点和最后一个终点的定位信息。


-----------------------------------------------------------------------
SVG中,图元的transform属性对渐变色绘制的影响:

- SVG先按照图元的坐标数据进行渐变色渲染,然后渐变色随同图元一起进行坐标变换(应用图元的transform属性)。这意味着在AGG中实现时,插值器矩阵需要叠加图元的transform属性。

- 对于objectBoundingBox模式,其参考坐标系是图元应用transform属性之前的包围矩形。


-----------------------------------------------------------------------
在SVG中:不论是绘制填充区域,还是绘制轮廓线,对于objectBoundingBox模式下的渐变色渲染,其参考坐标系均为填充区域的包围矩形。


-----------------------------------------------------------------------
使用AGG实现objectBoundingBox模式的渐变色绘制的步骤:

1 以单位矩形为基准,设计渐变方式和参考值区间。
2 对插值器矩阵应用gradientTransform中的变换(注意按逆序),此时得到的渐变区域仍然基于单位矩形。
3 通过缩放(w,h)和平移(x0,y0),将渐变区域变换至待填充图元的包围矩形。(x0,y0,w,h)是包围矩形在绝对坐标系中的几何参数。

上述方法还存在一个问题。首先分析一下像素颜色的计算过程:

1 待填充的像素通过插值器矩阵(上述变换的逆矩阵),变换至单位矩形。
2 计算参考值,并将参考值映射至颜色区间,从而得到像素颜色。在此过程中,已变换至单位矩形的点坐标和参考值区间[d1,d2]均换算成亚像素坐标(其实就是乘以16然后取整)参与计算。

由于单位矩形的边长换算成亚像素只有16,而参考值区间又是以单位矩形为基准选取的,因此参考值区间对应的亚像素数目有限,导致映射至颜色区间后,颜色看上去不连续。

解决办法:以边长w的正方形为基准,设计渐变方式和参考值区间,gradientTransform属性中的相对长度也乘以w,然后缩放系数改为(1,h/w)。

但是在绘制SVG图元前,gradientTransform属性已经被解析为一个矩阵,如何实现“相对长度乘以w”?参考《计算机图形学 第三版》P201 公式5.42,将矩阵的平移项(第3列前两个元素)乘以w即可。


-----------------------------------------------------------------------
SVG中,objectBoundingBox模式的渐变色绘制的实现原理:

在objectBoundingBox模式下,<linearGradient>和<radialGradient>的属性参数所设定的渐变区域,是以单位矩形(边长为1)为基准,然后通过缩放(w,h)和平移(x0,y0),变换至待填充图元的包围矩形。(x0,y0,w,h)是包围矩形在绝对坐标系中的几何参数。


-----------------------------------------------------------------------
SVG中,<linearGradient>使用向量标识渐变方向。用AGG实现时,通常使用水平渐变gradient_x,以原点为渐变起始点,参考值区间为[0,向量长度],然后通过插值器矩阵的旋转、平移,变换至渐变向量的位置。

要考虑向量长度近似为0的情况:如果向量长度 < 0.5,则按实色填充,填充色取第一个渐变色。


-----------------------------------------------------------------------
关于SVG中线性渐变元素<linearGradient>的描述:

属性:
    id            元素标识
    x1, y1        渐变矢量的起点,缺省值“0, 0”
    x2, y2        渐变矢量的终点,缺省值“100%, 0”

    gradientUnits    x1 y1 x2 y2的坐标系,缺省值为“objectBoundingBox”
      - userSpaceOnUse        用户坐标系(与SVG图元使用同一个坐标系)
      - objectBoundingBox    以对象的包围矩形为参考坐标系

    spreadMethod    重复方式,默认值为“pad”
      - pad            不重复
      - repeat            对应agg::gradient_repeat_adaptor
      - reflect            对应agg::gradient_reflect_adaptor

    xlink:href        引用另外一个已定义好的渐变元素

    gradientTransform    变换矩阵,缺省值为单位阵
        与图元的transform属性类似,也是按逆序应用变换(绝对坐标系)
        用于AGG中的插值器时,矩阵还要求逆
        gradientUnits对gradientTransform有影响
          - userSpaceOnUse    坐标变换使用用户坐标系(与SVG图元使用同一个坐标系)
              在此情况下,不需要对坐标值和变换矩阵进行额外处理
          - objectBoundingBox    坐标变换以对象的包围矩形为参考坐标系
              * translate(x,y)中,参数x,y是相对长度
              * rotate(angle,cx,cy)中,cx,cy是相对长度
              * 注意:这里的相对长度不支持百分比,只能用小数

如果x1 y1 x2 y2 gradientUnits均使用缺省值,填充效果如何?
经测试,等效于 (x1,y1) = (0,0)  (x2,y2) = (1,0)

如果x1 y1 x2 y2使用缺省值,gradientUnits=userSpaceOnUse,填充效果如何?
经测试&

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值