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  }