xps坐标计算

xps 之Positioning Content

1. RenderTransform and Transform

  • RenderTransform 和 Transform指定一个矩阵,表示做表空间变换

  • 该矩阵含6个元素,表示如下:

[xScale,sin Θ,-sin Θ,yScale,offsetX,offsetY]
  • xScale,yScale表示尺度变化,offsetX,offsetY表示偏移

  • glyphs节点的每个字符的坐标信息计算时,其坐标值由canvasRenderTransformMatrix和glyphRenderTransformMatrix共同决定

1.1 canvasRenderTransformMatrix计算

def extractGlyphs(glyphs,dstPageDic):
    global order
    canvasRenderTransformMatrix = [1,0,0,1,0,0]
    glyphsParent = glyphs.getparent()
    if 'Canvas' in glyphsParent.tag:
        attribDic = glyphsParent.attrib
        if attribDic.has_key('RenderTransform'):
            canvasRenderTransformMatrix = [float(item) for item in attribDic['RenderTransform'].split(',')]

  • 即父节点含'Canvas'标签,且有RenderTransform属性,则用父节点的RenderTransform值,否则为[1 0 0 1 0 0]

1.2 glyphRenderTransformMatrix计算

glyphRenderTransformMatrix = [float(item) for item in attribDic['RenderTransform'].split(',')] if attribDic.has_key('RenderTransform') else [1,0,0,1,0,0]

  • 即自身节点有RenderTransform属性,则用自身节点的RenderTransform值,不含RenderTransform属性,则为[1 0 0 1 0 0]

2. Indices

计算宽度占比用

Indices含义如下:

一个glyphs节点如下:

<Glyphs Fill="#ff000000" 
   FontUri="/Documents/1/Resources/Fonts/584FF68E-07BF-4D9B-954B-30DACA51E97E.odttf" 
   FontRenderingEmSize="12.0005" 
   StyleSimulations="None" 
   OriginX="58.88"
   OriginY="73.28" 
   Indices="5627;2047;29"
   UnicodeString="性别:" />

其中,OriginX,OriginY为首字符左下角的原始坐标系的x,y,需要转化到变换后的坐标系,计算思路如下:

2.1 对于该节点的第一个字符:性

  • 如果其len(indices) == 1:即只有一个索引,
x = canvasRenderTransformMatrix[0]*(glyphRenderTransformMatrix[0]*OriginX+glyphRenderTransformMatrix[4])+canvasRenderTransformMatrix[4]
y = canvasRenderTransformMatrix[3]*(glyphRenderTransformMatrix[3]*OriginY+glyphRenderTransformMatrix[5])+canvasRenderTransformMatrix[5]
w = w * glyphRenderTransformMatrix[0] * (50 if ord(UnicodeString[i].decode()) >=32 and ord(UnicodeString[i].decode())<=126 else 100)/100
h = h * glyphRenderTransformMatrix[3]
  • 多个索引的时候,w,h的计算分别要考虑宽度百分比

  • x,y为变换后的起始点坐标,w,h,为字宽

2.2 对于后边的字符,需要通过计算前边所有字符的宽度之和来计算当前字的x,y,w,h: 别:

其中前边字符宽度和算法为:

widthSum = widthSum + float(( IndicesList[j].split(',')[1] if len(IndicesList[j].split(','))>1 else (50 if ord(UnicodeString[j].decode()) >=32 and ord(UnicodeString[j].decode())<=126 else 100) ))

其中,每个字符宽算法为:

float(( IndicesList[j].split(',')[1] if len(IndicesList[j].split(','))>1 else (50 if ord(UnicodeString[j].decode()) >=32 and ord(UnicodeString[j].decode())<=126 else 100) ))

即:

  • 若果只有一个索引,则看当前字符是全角还是半角,全角宽占比100,半角50
  • 若有多个索引,则用indiceList[1],即宽度

然后需要通过宽度百分比和FontRenderingEmSize算出前边字符宽之和,以得到当前的x,y,w,h,其中,w,h的算法要看indices的长度而定
如:

widthSum = widthSum/100 * FontRenderingEmSize
if len(indices) == 1:
    x = canvasRenderTransformMatrix[0]*(glyphRenderTransformMatrix[0]*(OriginX+widthSum)+glyphRenderTransformMatrix[4])+canvasRenderTransformMatrix[4]
    y = canvasRenderTransformMatrix[3]*(glyphRenderTransformMatrix[3]*OriginY+glyphRenderTransformMatrix[5])+canvasRenderTransformMatrix[5]
。。。
elif len(indices) == 4:
    x = canvasRenderTransformMatrix[0]*(glyphRenderTransformMatrix[0]*(OriginX+FontRenderingEmSize*float(indices[2])/100)+glyphRenderTransformMatrix[4])+canvasRenderTransformMatrix[4]
    y = canvasRenderTransformMatrix[3]*(glyphRenderTransformMatrix[3]*(OriginY-FontRenderingEmSize*float(indices[3])/100)+glyphRenderTransformMatrix[5])+canvasRenderTransformMatrix[5]  #加上voffset
    w = w * glyphRenderTransformMatrix[0] * float(indices[1])/100
    h = h * glyphRenderTransformMatrix[3]
                aw = float(indices[1])
  • 其中len(indices) == 4的为即有偏移又有宽度比的情况

小结

有了这些,我们就可一提取到每个字符的坐标信息了, 今儿为后续进展作准备。

posted @ 2018-07-03 21:09  moonok  阅读(473)  评论(0编辑  收藏  举报