github.com/signintech/pdft@v0.5.0/minigopdf/content_obj.go (about) 1 package gopdf 2 3 import ( 4 "bytes" 5 "compress/zlib" 6 "strconv" 7 "strings" 8 ) 9 10 // ContentObj content object 11 type ContentObj struct { //impl IObj 12 buffer bytes.Buffer 13 stream bytes.Buffer 14 listCache listCacheContent 15 //text bytes.Buffer 16 getRoot func() *GoPdf 17 } 18 19 func (c *ContentObj) protection() *PDFProtection { 20 return c.getRoot().protection() 21 } 22 23 func (c *ContentObj) init(funcGetRoot func() *GoPdf) { 24 c.getRoot = funcGetRoot 25 } 26 27 func (c *ContentObj) build(objID int) error { 28 buff, err := c.listCache.toStream(c.protection()) 29 if err != nil { 30 return err 31 } 32 isFlate := (c.getRoot().compressLevel != zlib.NoCompression) 33 34 //zipvar buff bytes.Buffer 35 var cPtr *bytes.Buffer // "Pointer to content" 36 if isFlate { 37 var zbuff bytes.Buffer 38 zwriter, err := zlib.NewWriterLevel(&zbuff, 39 c.getRoot().compressLevel) 40 if err != nil { 41 // should never happen... 42 return err 43 } 44 c.stream.WriteTo(zwriter) 45 buff.WriteTo(zwriter) 46 zwriter.Close() 47 cPtr = &zbuff 48 } else { 49 // zlib compressLevel = 0 adds header and thus 50 // needs /FlateDecode => pass through 51 buff.WriteTo(&c.stream) 52 cPtr = &c.stream 53 } 54 streamlen := (*cPtr).Len() 55 c.buffer.WriteString("<<\n") 56 if isFlate { 57 c.buffer.WriteString("/Filter/FlateDecode") 58 } 59 c.buffer.WriteString("/Length " + strconv.Itoa(streamlen) + "\n") 60 c.buffer.WriteString(">>\n") 61 c.buffer.WriteString("stream\n") 62 if c.protection() != nil { 63 tmp, err := rc4Cip(c.protection().objectkey(objID), (*cPtr).Bytes()) 64 if err != nil { 65 return err 66 } 67 c.buffer.Write(tmp) 68 c.buffer.WriteString("\n") 69 } else { 70 c.buffer.Write((*cPtr).Bytes()) 71 if isFlate { 72 c.buffer.WriteString("\n") 73 } 74 } 75 c.buffer.WriteString("endstream\n") 76 return nil 77 } 78 79 func (c *ContentObj) getType() string { 80 return "Content" 81 } 82 83 func (c *ContentObj) getObjBuff() *bytes.Buffer { 84 return &(c.buffer) 85 } 86 87 // AppendStreamText append text 88 func (c *ContentObj) AppendStreamText(text string) error { 89 90 //support only CURRENT_FONT_TYPE_SUBSET 91 textColor := c.getRoot().curr.textColor() 92 grayFill := c.getRoot().curr.grayFill 93 fontCountIndex := c.getRoot().curr.Font_FontCount + 1 94 fontSize := c.getRoot().curr.Font_Size 95 fontStyle := c.getRoot().curr.Font_Style 96 x := c.getRoot().curr.X 97 y := c.getRoot().curr.Y 98 setXCount := c.getRoot().curr.setXCount 99 fontSubset := c.getRoot().curr.Font_ISubset 100 101 cache := cacheContentText{ 102 fontSubset: fontSubset, 103 rectangle: nil, 104 textColor: textColor, 105 grayFill: grayFill, 106 fontCountIndex: fontCountIndex, 107 fontSize: fontSize, 108 fontStyle: fontStyle, 109 setXCount: setXCount, 110 x: x, 111 y: y, 112 pageheight: c.getRoot().curr.pageSize.H, 113 contentType: ContentTypeText, 114 lineWidth: c.getRoot().curr.lineWidth, 115 } 116 117 var err error 118 c.getRoot().curr.X, c.getRoot().curr.Y, err = c.listCache.appendContentText(cache, text) 119 if err != nil { 120 return err 121 } 122 123 return nil 124 } 125 126 // AppendStreamSubsetFont add stream of text 127 func (c *ContentObj) AppendStreamSubsetFont(rectangle *Rect, text string, cellOpt CellOption) error { 128 129 textColor := c.getRoot().curr.textColor() 130 grayFill := c.getRoot().curr.grayFill 131 fontCountIndex := c.getRoot().curr.Font_FontCount + 1 132 fontSize := c.getRoot().curr.Font_Size 133 fontStyle := c.getRoot().curr.Font_Style 134 x := c.getRoot().curr.X 135 y := c.getRoot().curr.Y 136 setXCount := c.getRoot().curr.setXCount 137 fontSubset := c.getRoot().curr.Font_ISubset 138 139 cache := cacheContentText{ 140 fontSubset: fontSubset, 141 rectangle: rectangle, 142 textColor: textColor, 143 grayFill: grayFill, 144 fontCountIndex: fontCountIndex, 145 fontSize: fontSize, 146 fontStyle: fontStyle, 147 setXCount: setXCount, 148 x: x, 149 y: y, 150 pageheight: c.getRoot().curr.pageSize.H, 151 contentType: ContentTypeCell, 152 cellOpt: cellOpt, 153 lineWidth: c.getRoot().curr.lineWidth, 154 } 155 var err error 156 c.getRoot().curr.X, c.getRoot().curr.Y, err = c.listCache.appendContentText(cache, text) 157 if err != nil { 158 return err 159 } 160 return nil 161 } 162 163 // AppendStreamLine append line 164 func (c *ContentObj) AppendStreamLine(x1 float64, y1 float64, x2 float64, y2 float64) { 165 //h := c.getRoot().config.PageSize.H 166 //c.stream.WriteString(fmt.Sprintf("%0.2f %0.2f m %0.2f %0.2f l s\n", x1, h-y1, x2, h-y2)) 167 var cache cacheContentLine 168 cache.pageHeight = c.getRoot().curr.pageSize.H 169 cache.x1 = x1 170 cache.y1 = y1 171 cache.x2 = x2 172 cache.y2 = y2 173 c.listCache.append(&cache) 174 } 175 176 // AppendStreamRectangle : draw rectangle from lower-left corner (x, y) with specif width/height 177 func (c *ContentObj) AppendStreamRectangle(x float64, y float64, wdth float64, hght float64, style string) { 178 var cache cacheContentRectangle 179 cache.pageHeight = c.getRoot().curr.pageSize.H 180 cache.x = x 181 cache.y = y 182 cache.width = wdth 183 cache.height = hght 184 cache.style = style 185 c.listCache.append(&cache) 186 } 187 188 // AppendStreamOval append oval 189 func (c *ContentObj) AppendStreamOval(x1 float64, y1 float64, x2 float64, y2 float64) { 190 var cache cacheContentOval 191 cache.pageHeight = c.getRoot().curr.pageSize.H 192 cache.x1 = x1 193 cache.y1 = y1 194 cache.x2 = x2 195 cache.y2 = y2 196 c.listCache.append(&cache) 197 } 198 199 // AppendStreamCurve draw curve 200 // - x0, y0: Start point 201 // - x1, y1: Control point 1 202 // - x2, y2: Control point 2 203 // - x3, y3: End point 204 // - style: Style of rectangule (draw and/or fill: D, F, DF, FD) 205 // D or empty string: draw. This is the default value. 206 // F: fill 207 // DF or FD: draw and fill 208 func (c *ContentObj) AppendStreamCurve(x0 float64, y0 float64, x1 float64, y1 float64, x2 float64, y2 float64, x3 float64, y3 float64, style string) { 209 var cache cacheContentCurve 210 cache.pageHeight = c.getRoot().curr.pageSize.H 211 cache.x0 = x0 212 cache.y0 = y0 213 cache.x1 = x1 214 cache.y1 = y1 215 cache.x2 = x2 216 cache.y2 = y2 217 cache.x3 = x3 218 cache.y3 = y3 219 cache.style = strings.ToUpper(strings.TrimSpace(style)) 220 c.listCache.append(&cache) 221 } 222 223 // AppendStreamSetLineWidth : set line width 224 func (c *ContentObj) AppendStreamSetLineWidth(w float64) { 225 var cache cacheContentLineWidth 226 cache.width = w 227 c.listCache.append(&cache) 228 } 229 230 // AppendStreamSetLineType : Set linetype [solid, dashed, dotted] 231 func (c *ContentObj) AppendStreamSetLineType(t string) { 232 var cache cacheContentLineType 233 cache.lineType = t 234 c.listCache.append(&cache) 235 236 } 237 238 // AppendStreamSetGrayFill set the grayscale fills 239 func (c *ContentObj) AppendStreamSetGrayFill(w float64) { 240 w = fixRange10(w) 241 var cache cacheContentGray 242 cache.grayType = grayTypeFill 243 cache.scale = w 244 c.listCache.append(&cache) 245 } 246 247 // AppendStreamSetGrayStroke set the grayscale stroke 248 func (c *ContentObj) AppendStreamSetGrayStroke(w float64) { 249 w = fixRange10(w) 250 var cache cacheContentGray 251 cache.grayType = grayTypeStroke 252 cache.scale = w 253 c.listCache.append(&cache) 254 } 255 256 // AppendStreamSetColorStroke set the color stroke 257 func (c *ContentObj) AppendStreamSetColorStroke(r uint8, g uint8, b uint8) { 258 var cache cacheContentColor 259 cache.colorType = colorTypeStroke 260 cache.r = r 261 cache.g = g 262 cache.b = b 263 c.listCache.append(&cache) 264 } 265 266 // AppendStreamSetColorFill set the color fill 267 func (c *ContentObj) AppendStreamSetColorFill(r uint8, g uint8, b uint8) { 268 var cache cacheContentColor 269 cache.colorType = colorTypeFill 270 cache.r = r 271 cache.g = g 272 cache.b = b 273 c.listCache.append(&cache) 274 } 275 276 // AppendStreamImage append image 277 func (c *ContentObj) AppendStreamImage(index int, x float64, y float64, rect *Rect) { 278 //fmt.Printf("index = %d",index) 279 h := c.getRoot().curr.pageSize.H 280 var cache cacheContentImage 281 cache.h = h 282 cache.x = x 283 cache.y = y 284 cache.rect = *rect 285 cache.index = index 286 c.listCache.append(&cache) 287 //c.stream.WriteString(fmt.Sprintf("q %0.2f 0 0 %0.2f %0.2f %0.2f cm /I%d Do Q\n", rect.W, rect.H, x, h-(y+rect.H), index+1)) 288 } 289 290 // ContentObj_CalTextHeight calculate height of text 291 func ContentObj_CalTextHeight(fontsize int) float64 { 292 return (float64(fontsize) * 0.7) 293 } 294 295 // When setting colour and grayscales the value has to be between 0.00 and 1.00 296 // This function takes a float64 and returns 0.0 if it is less than 0.0 and 1.0 if it 297 // is more than 1.0 298 func fixRange10(val float64) float64 { 299 if val < 0.0 { 300 return 0.0 301 } 302 if val > 1.0 { 303 return 1.0 304 } 305 return val 306 } 307 308 func convertTTFUnit2PDFUnit(n int, upem int) int { 309 var ret int 310 if n < 0 { 311 rest1 := n % upem 312 storrest := 1000 * rest1 313 //ledd2 := (storrest != 0 ? rest1 / storrest : 0); 314 ledd2 := 0 315 if storrest != 0 { 316 ledd2 = rest1 / storrest 317 } else { 318 ledd2 = 0 319 } 320 ret = -((-1000*n)/upem - int(ledd2)) 321 } else { 322 ret = (n/upem)*1000 + ((n%upem)*1000)/upem 323 } 324 return ret 325 }