I am using podofo for doing PDF operations, like adding annotations, signatures etc as per my requirement in my iOS application. I have first tried the only sample for the podofo library available which works great. But the problem with the sample is the annotations added doesn't show in any preview like Google, Adobe Reader etc. Thats a problem.
As per few guideline from Adobe I found that it requires to have Appearance Key for the FreeText annotation to appear. I have tried analyzing raw pdf file in a text editor to see the difference in the PDF which has correct Annotations, with podofo created PDF annotations. I found there are AP N keys with a stream object that is in encoded form for the annotation, which was missing from podofo sample.
Then after searching I found podofo's own sample and tried to use the code, which seems to be doing correctly, but didn't work either, I know I am missing something, but not sure what, and where, please have a look of the code below
+(void)createFreeTextAnnotationOnPage:(NSInteger)pageIndex doc:(PdfMemDocument*)aDoc rect:(CGRect)aRect borderWidth:(double)bWidth title:(NSString*)title content:(NSString*)content bOpen:(Boolean)bOpen color:(UIColor*)color {
PoDoFo::PdfMemDocument *doc = (PoDoFo::PdfMemDocument *) aDoc;
PoDoFo::PdfPage* pPage = doc->GetPage(pageIndex);
if (! pPage) {
// couldn't get that page
return;
}
PoDoFo::PdfRect rect;
rect.SetBottom(aRect.origin.y);
rect.SetLeft(aRect.origin.x);
rect.SetHeight(aRect.size.height);
rect.SetWidth(aRect.size.width);
PoDoFo::PdfString sTitle(reinterpret_cast<const PoDoFo::pdf_utf8*>([title UTF8String]));
PoDoFo::PdfString sContent(reinterpret_cast<const PoDoFo::pdf_utf8*>([content UTF8String]));
PoDoFo::PdfFont* pFont = doc->CreateFont( "Helvetica", new PoDoFo::PdfIdentityEncoding( 0, 0xffff, true ) );
std::ostringstream oss;
oss << "BT" << std::endl << "/" << pFont->GetIdentifier().GetName()
<< " " << pFont->GetFontSize()
<< " Tf " << std::endl;
[APDFManager WriteStringToStream:sContent :oss :pFont];
oss << "Tj ET" << std::endl;
PoDoFo::PdfDictionary fonts;
fonts.AddKey(pFont->GetIdentifier().GetName(), pFont->GetObject()->Reference());
PoDoFo::PdfDictionary resources;
resources.AddKey( PoDoFo::PdfName("Fonts"), fonts );
PoDoFo::PdfAnnotation* pAnnotation =
pPage->CreateAnnotation( PoDoFo::ePdfAnnotation_FreeText, rect );
pAnnotation->SetTitle( sTitle );
pAnnotation->SetContents( sContent );
//pAnnotation->SetAppearanceStream( &xObj );
pAnnotation->GetObject()->GetDictionary().AddKey( PoDoFo::PdfName("DA"), PoDoFo::PdfString(oss.str()) );
pAnnotation->GetObject()->GetDictionary().AddKey( PoDoFo::PdfName("DR"), resources );
}
+(void) WriteStringToStream:(const PoDoFo::PdfString & )rsString :(std::ostringstream &) oss :(PoDoFo::PdfFont*) pFont
{
PoDoFo::PdfEncoding* pEncoding = new PoDoFo::PdfIdentityEncoding( 0, 0xffff, true );
PoDoFo::PdfRefCountedBuffer buffer = pEncoding->ConvertToEncoding( rsString, pFont );
PoDoFo::pdf_long lLen = 0;
char* pBuffer = NULL;
std::auto_ptr<PoDoFo::PdfFilter> pFilter = PoDoFo::PdfFilterFactory::Create( PoDoFo::ePdfFilter_ASCIIHexDecode );
pFilter->Encode( buffer.GetBuffer(), buffer.GetSize(), &pBuffer, &lLen );
oss << "<";
oss << std::string( pBuffer, lLen );
oss << ">";
free( pBuffer );
delete pEncoding;
}
Any one in SO universe can please tell me what's wrong with above code, and how to add a correct FreeText Annotation so that it appears correctly everywhere.
Many Thanks.
The annotation in question looks like this:
19 0 obj
<<
/Type/Annot
/Contents(þÿ M Y A N N O T A T I O N)
/DA(BT\n/Ft18 12 Tf \n 1 0 0 rg \n<002D003900000021002E002E002F0034002100340029002F002E>Tj ET\n)
/DR<</Fonts<</Ft18 18 0 R>>>>
/M(D:20140616141406+05'00')
/P 4 0 R
/Rect[ 188.814117 748.970520 467.849731 795.476456]
/Subtype/FreeText
/T(þÿ A n n o t a t e P D F)
>>
endobj
Three observations:
It has a Default Appearance but not APpearance streams.
The contents of the Default Appearance are invalid.
The Default Resources are in the wrong object.
Item 1 may cause the appearance not to render in many simple viewers which only show finalized stuff (page content, annotation appearances, ...) but don't create appearances from the Default Appearance. You should, therefore, also supply an appearance stream.
Items 2 and 3 may cause the appearance not to render in more complex viewers which do try to create appearances from the Default Appearance and Default Resources but expect the DA to be correct and the DR correctly located. You should, therefore, correct the DA and move the DR.
In detail...
1 - Default Appearance but not APpearance streams
While according to the specification ISO 32000-1 the DA is required for free text annotation and AP is not, simpler PDF viewers may not have built-in code to create an appearance stream from the default appearance.
This is not completely surprising: While in case of your PDF there is not much to do, applying the default to some content can imply calculating the best size for text to fit into some area and similar tasks. Thus, simple, incomplete viewers tend to not implement this.
2 - Default Appearance contents are invalid
Your DA string contains BT and ET operators. If you look at section 12.7.3.3 Variable Text of ISO 32000-1, though, you'll see that during appearance creation the contents of DA are embedded into a BT .. ET envelope:
The appearance stream includes the following section of marked content, which represents the portion of the stream that draws the text:
/Tx BMC % Begin marked content with tag Tx
q % Save graphics state
… Any required graphics state changes, such as clipping …
BT % Begin text object
… Default appearance string ( DA ) …
… Text-positioning and text-showing operators to show the variable text …
ET % End text object
Q % Restore graphics state
EMC % End marked content
The default appearance string (DA) contains any graphics state or text state operators needed to establish the graphics state parameters, such as text size and colour, for displaying the field’s variable text. Only operators that are allowed within text objects shall occur in this string
But BT and ET are not allowed inside another BT .. ET text object!
Furthermore you add the text content inside your DA. As you see above, the text drawing operations are added right after your DA contents. Thus, you're in danger of having duplicate texts eventually.
3 - Default Resources dislocation
You have the Default Resources in the annotation dictionary. But the section 12.7.3.3 Variable Text of ISO 32000-1 mentioned above indicates:
The specified font value shall match a resource name in the Font entry of the default resource dictionary (referenced from the DR entry of the interactive form dictionary).
Thus, your DR will be ignored and are expected elsewhere. So your choice of font may at best be ignored
I am working on the similar things. I tried generating appearance stream manually, but found it's difficult. Actually the podofo sample code you post above works, but it's wrong in the way of adding appearance stream. You can't use SetAppearanceStream which is wrong either.
podofo's PdfPainter can draw text. It generates text stream. It looks like working for PdfPage only, but actually it works for XObject too. It's really a hidden feature!
My code sample:
PdfFont *pFont = ...;
// Add XObject
PdfXObject xObj(borderPdfRect, pPdfMemDocument);
PdfPainter painter;
painter.SetPage(&xObj);
painter.Save(); // Save graphics settings
// Draw text
painter.SetFont(pFont);
painter.GetFont()->SetFontSize(fontSize);
painter.SetColor(self.textColor.color.red, self.textColor.color.green, self.textColor.color.blue);
PdfString pdfStr(reinterpret_cast<const pdf_utf8*>([self.text UTF8String]));
painter.DrawMultiLineText(textPdfRect, pdfStr);
painter.Restore();
painter.FinishPage();
// Add xObj as appearance stream. Don't use SetAppearanceStream
PdfDictionary dict;
dict.AddKey("N", xObj.GetObject()->Reference());
pTextAnno->GetObject()->GetDictionary().AddKey("AP", dict);
Related
table = document.add_table(rows=1, cols=1)
hdr_cells = table.rows[0].cells
hdr_cells[0].text = 'Qty'
I have to change font size of text 'Qty' in table with one row and one column, how can I make it?
You need to get the paragraph in the cell. From the documentation of python-docx:
3.5.2 _Cell objects:
class docx.table._Cell (tc, parent)
paragraphs
List of paragraphs in the cell. A table cell is required to
contain at least one block-level element and end with a paragraph. By
default, a new cell contains a single paragraph. Read-only
Reference: python-docx Documentation - Read the Docs
The code:
To change font size of text 'Qty'
paragraph =hdr_cells[0].paragraphs[0]
run = paragraph.runs
font = run[0].font
font.size= Pt(30) # font size = 30
To change font size of the whole table:
for row in table.rows:
for cell in row.cells:
paragraphs = cell.paragraphs
for paragraph in paragraphs:
for run in paragraph.runs:
font = run.font
font.size= Pt(30)
Reference of how to access paragraphs in a table: Extracting data from tables
Up there the solution really helped. I use it for a while. But I found a tiny problem:time. As your table grows bigger the time you cost to build the table getting longer. So I improve it. Cut two rounds. Here you are:
The code changes the whole table
for row in table.rows:
for cell in row.cells:
paragraphs = cell.paragraphs
paragraph = paragraphs[0]
run_obj = paragraph.runs
run = run_obj[0]
font = run.font
font.size = Pt(30)
When you cut two rounds you save the time
Building on user7609283 answer, here is a short version to set a cell to bold (the cell must contain text before applying format as it looks for the first paragraph):
row_cells = table.add_row().cells
row_cells[0].text = "Customer"
row_cells[0].paragraphs[0].runs[0].font.bold = True
This font change applies to all cells of a table and is streamlined. All cells must contain text before being formatted or an index out of range error is thrown:
for row in table.rows:
for cell in row.cells:
cp = cell.paragraphs[0].runs
cp[0].font.size = Pt(14)
This next font change applies to a single cell as wanted, in this case the top left cell:
tc = table.cell(0, 0).paragraphs[0].runs
tc[0].font.size = Pt(14)
I am trying to get my text labels to automatically resize if the text is longer than the box they are in. I also want it to support multi-line functionality. I have done some searching online and saw that it used to work something like this:
CCLabelTTF::labelWithString(“This is a sentence longer than a line width.2d-x”, CGSizeMake(**0, 0**), UITextAlignmentCenter, “Thonburi”, 20);
but that seems to no longer be available in cocos so I am not sure what to do.. Right now I have my label set up as follows:
myQuestion = Label::createWithTTF("Testing to see if text wrap will work" ,c_strFontNameBase, 50);
myQuestion->setPosition(boxLabel->getContentSize().width/2, boxLabel->getContentSize().height/2);
boxLabel->addChild(myQuestion, 50);
Is there some way I can use a similar way to the top example to make mine work? This doesn't seem like it should be very hard thing to do but I am finding a lack of documentation on it online...
I believe, you can only make one dimension of the label auto-resizable i.e. either width or height can be auto-resizable. By default when you create label as follows, width of the labels are set to resize automatically with fixed height:
auto label = Label::createWithTTF("Hello World gsdhsgdh gshdghsg yutywe gdgshdgy bnbjh hshhashgy hjnbdnsdhh ghhsgdhg ghghghsd ghhghsd ghghghgsd jkjkhsdjkj ououisdusydsi kkjkxncmxcjh kcxhjxhcjx jkuiushjxchxjch hjhjchxuyuychjc ", "fonts/Marker Felt.ttf", 24);
// position the label on the center of the screen
label->setPosition(Vec2(origin.x + visibleSize.width/2,
origin.y + visibleSize.height - label->getContentSize().height));
// add the label as a child to this layer
this->addChild(label, 1);
But if you want multi-line support i.e. fixed width and resizable height you just need to set dimension of the label with fixed width and zero height as:
label->setDimensions(300, 0);
I hope it will help.
I'm using GetTextExtentPoint32W to get width of a text in a cell in MS Excel 2010. The cell width is fetched using ActiveCell.Width. These two widths are then compared to determine whether the text fits in the cell or extends out of the cell.
Visually, even though the text fits perfectly in the cell, the text width returned by the method is more than the cell width. Also, when I increase the font size the difference between actual text width and that returned by the method increases.
Following is a part of the source code used to achieve the result. Please help me solve this error.
hDC = ctypes.windll.user32.GetDC(self.windowHandle)
tempBMP = ctypes.windll.gdi32.CreateCompatibleBitmap(hDC, 1, 1)
hBMP = ctypes.windll.gdi32.SelectObject(hDC, tempBMP)
iFontSize = self.excelCellObject.Font.Size
deviceCaps = ctypes.windll.gdi32.GetDeviceCaps(hDC, 90)
iFontSize = int(iFontSize)
iFontSize = ctypes.c_int(iFontSize)
iFontSize = ctypes.windll.kernel32.MulDiv(iFontSize, deviceCaps, 72)
iFontSize = iFontSize * -1
iFontWeight = 700 if self.excelCellObject.Font.Bold else 400
sFontName = self.excelCellObject.Font.Name
sFontItalic = self.excelCellObject.Font.Italic
sFontUnderline = True if self.excelCellObject.Font.Underline else False
sFontStrikeThrough = self.excelCellObject.Font.Strikethrough
#Create a font object with the correct size, weight and style
hFont = ctypes.windll.gdi32.CreateFontW(iFontSize,
0, 0, 0,
iFontWeight,
sFontItalic,
sFontUnderline,
sFontStrikeThrough,
False, False, False,
False, False,
sFontName)
#Load the font into the device context, storing the original font object
hOldFont = ctypes.windll.gdi32.SelectObject(hDC, hFont)
sText = self.excelCellObject.Text
log.io("\nText \t"+sText+"\n")
textLength = len(sText)
class structText(ctypes.Structure):
_fields_ = [("width", ctypes.c_int),
("height",ctypes.c_int)]
StructText = structText()
getTextExtentPoint = ctypes.windll.gdi32.GetTextExtentPoint32W
getTextExtentPoint.argtypes = [ctypes.c_void_p,
ctypes.c_char_p,
ctypes.c_int,
ctypes.POINTER(structText)]
getTextExtentPoint.restype = ctypes.c_int
#Get the text dimensions
a = ctypes.windll.gdi32.GetTextExtentPoint32W(hDC,
sText,
textLength,
ctypes.byref(StructText))
#Delete the font object we created
a = ctypes.windll.gdi32.DeleteObject(hFont)
a = ctypes.windll.gdi32.DeleteObject(tempBMP)
#Release the device context
a = ctypes.windll.user32.ReleaseDC(self.windowHandle, hDC)
textWidth = StructText.width
cellWidth = self.excelCellObject.Width
Thanks.
I do not use Python or Excel 2010 so cannot comment on your current approach. However, I have struggled with a similar problem. I hope the following points will be helpful.
Background
If you hover over the right boundary of an Excel column and hold the left mouse button you will get a display of the format: “Width: n.nn (mm pixels)”.
The help for the ColumnWidth property says:
One unit of column width is equal to the width of one character in the
Normal style. For proportional fonts, the width of the character 0
(zero) is used.
Use the Width property to return the width of a column in points.
As far as I can tell, “Normal style” means the standard font name and size at the time the workbook was created. Changing the standard font name and size for an existing workbook does not appear to have any effect. Changing the font name and size for a worksheet has no effect.
Two example displays for a standard width column are:
For Arial 10 Width: 8.43 (64 pixels)
For Tahoma 10.5 Width: 8.38 (72 pixels)
I have created a string of zeros and attempted to measure how many are visible depending on the width of the column. I found the number of zeroes that I could see matched the value displayed reasonably well for such as subjective measure.
With VBA, the ColumnWidth property of a column or cell sets or returns the width in characters.
With VBA, The read only Width property of a column or cell returns .75 * the width in pixels.
The significance of the above information is that the width values obtained from Excel are not necessarily correct for the font being used.
My problem and the solution I discovered
The problem I had was that I was merging cells and filling them with text. Although Excel will adjust the height of a row so the text within an unmerged cell is visible, it will not do so for a merged cell. I tried many techniques including Microsoft’s .Net, text rendering routines without success. Nothing I tried would reliably emulate Excel’s system for determining the width of text.
The technique I eventually used successfully involved picking a cell to the right and below all used cells for experimental use. I adjusted the width of the experimental cell’s column to match the combined width of the merged cell and copied the formatted value from the cell whose height I wanted. Because the experimental cell was unmerged, Excel would adjust the height as appropriate. I then made sure the source row was at least this height.
The key feature of this technique was that I was not trying to emulate Excel’s system for determining the width of text; I was using Excel’s system.
You would need to try different column widths for the experimental cell. I would start with the current width of the source column. If the row height matches that for a single row, the width of the source column is already sufficient. If the row height is more than that for a single row, I would increase the column width until the row height matched that for a single row and then adjust the source column’s width to match. If you start with the widest value (in characters or Python’s text width) you will probably get the source column width correct at the first attempt which would avoid the need for later adjustments.
I am generating a clickable (=with links) table of contents. In order to emphasize the 'clickability' of the entries I want them colored as links (i.e. blue color and underline).
I have this code for setting the style:
toc = TableOfContents()
toc.levelStyles[0].fontName = 'Arial Bold'
toc.levelStyles[0].fontSize = 12
toc.levelStyles[0].textColor = '#0000cc'
and use this code to add each entry:
toc.addEntry(0, '<u>' + entrytext + '</u>', pageNum, str(id(page)))
It works ok, the problem is that page numbers turn out blue as well. I tried to look around SO and the user guide for ways to put a different style for each - but was unsuccessful. Any ideas?
Thanks.
I have file aa with a variable x which is labeled with value label x_lab. I would like to use this value label on the variable x of Stata file bb:
use bb, clear
label value x x_lab
How can I import the value label x_lab?
You can use label save, which saves value labels in a do-file:
label save x_lab using label.do
use bb, clear
do label.do
See Stata help for label.
This answer technique didn't work for me as I wanted the variable labels created with e.g. label var connected "connected household", not the value labels.
Instead I used this advice: http://statalist.1588530.n2.nabble.com/st-How-to-export-variables-window-td3937733.html
*************
sysuse auto, clear
log using mylog, name(newlog) replace
foreach var of varlist _all{
di _col(3) "`var'" _col(20) "`:var label `var''"
}
log close newlog
//translate from proprietary format
translate mylog.smcl mylog.txt, replace
!start mylog.txt
*************
To fix the labels that extended over multiple lines so they just used a single one, I then replaced the \n > for the oversized labels with nothing (in regex mode in atom). I could easily save into TSV from there.
Specifically:
Clean up header and footer text in the logfile output.
On Mac: use "\n" instead of "\r\n".
On Windows: first "\r\n -> ""
then whitespace at beginning "\r\n " --> "\r\n"
then convert whitespace with 3 or more spaces in middle to tabs " +" --> "\t"
(Edit manually additional errors on tab if there are still some left)
save as mylog.tsv
open in Excel, and use table of labels as needed.