For a small side project, I need to have all glyph names available in a font. So, I thought to make this:
CTFontRef f = CTFontCreateWithName(CFSTR("Zapfino"), 40, NULL);
CFIndex count = CTFontGetGlyphCount(f);
printf("There are %ld glyphs\n", count);
for (CGGlyph i = 1; i < count + 1; i++)
{
CTGlyphInfoRef gi = CTGlyphInfoCreateWithGlyph(i, f, CFSTR("(c)"));
CFStringRef name = CTGlyphInfoGetGlyphName(gi);
CGFontIndex idx = CTGlyphInfoGetCharacterIdentifier(gi);
printf("Glyph: %4hu, idx: %4hu ", i, idx);
CFShow(name);
printf("\n");
}
Creating the font and getting the glyph count works just fine. The name of the glyph is always NULL though. The CTGlyphInfoRef variable 'gi' gets a value. Any thoughts? What am I missing here?
You've misunderstood what CTGlyphInfo is about. It's not a way to query for information about a glyph. It's a representation of a substitution of a glyph for a string. You can set a glyph info object as the value for the kCTGlyphInfoAttributeName attribute in an attributed string. That glyph then replaces that range of attributed text, if the text matches the base string.
You can use CGFontCopyGlyphNameForGlyph() to get the name for a glyph from a font. You can create the CGFontRef directly using the CGFontCreate...() functions. You can also create one from a CTFont using CTFontCopyGraphicsFont().
Related
my aim is to capture the screen of a windows form using c++/cli. Below is the code to capture the window, however, it is in C#. What changes do I have to make to the code for it to work in c++?
Graphics myGraphics = this.CreateGraphics();
Size s = this.Size;
memoryImage = new Bitmap(s.Width, s.Height, myGraphics);
Graphics memoryGraphics = Graphics.FromImage(memoryImage);
memoryGraphics.CopyFromScreen(this.Location.X, this.Location.Y, 0, 0, s);
What I've tried:
I've tried using the code below in c++, however, I get errors for the part in ** **.
The error says expected a ; after Size i.e. Size; s = this->Size; which does not make sense to me
Graphics^ myGraphics = this->CreateGraphics();
Size **s** = this->Size;
memoryImage = gcnew Bitmap(**s**->Width, s->Height, myGraphics);
Graphics^ memoryGraphics = Graphics::FromImage(memoryImage);
memoryGraphics->CopyFromScreen(this->Location.X, this->Location.Y, 0, 0, s);
Your code looks mostly correct.
I think that Size s is getting confused because Size is both the name of a type, and the name of a property on this object. It thinks you're trying to retrieve the Size property and throw away the result. To fix this, use the full name of the type for the declaration: System.Drawing.Size s = this->Size;. (You could also use auto, or remove the local variable entirely and just call this->Size several times.)
System.Drawing.Size is a value struct, not a ref class. It's a value type, not a reference type, so you need to do s.Width and s.Height.
This is similar to Location: Location returns a Point, which is a value type, and you're already doing Location.X, not Location->X.
I've been tying to build a simple Win Api program (using CodeBlocks) and ran into a weird problem.
case WM_COMMAND:{
if (LOWORD(wParam) == Calculate) {
int A=0, ArrayReset = 0;
char textread[256];
SendMessage((HWND)Box1,(UINT) EM_GETLINE, (WPARAM)1, (LPARAM)&textread);
A = atoi(textread);
itoa(ArrayReset, textread, 10);
itoa(A, textread, 10);
SendMessage((HWND)Box1,(UINT) WM_SETTEXT, (WPARAM)1,(LPARAM)&textread);
(My program is a bit more complicated, but this is just to show the problematic point)
Now, what I expect the code to do is to read the value in Box1, convert it into integer, convert it back to char array, and print this array back on the same Box1. Basically, some converting with no difference in the end result.
However, there is this strange problem. The code works with single digit numbers just fine, but if I enter a number with more digits, like 12 or 356, I get 1200 and 3560 respectively. If the input number is bigger than a thousand, it works fine again.
Is this a problem because of my method of resetting array's value back to 0, or does it have to do something with the conversion processes?
There are some mistakes in this code.
For starters, (LPARAM)&textread should be either (LPARAM)textread or (LPARAM)&textread[0].
But more importantly, you are not preparing the EM_GETLINE message correctly:
lParam
A pointer to the buffer that receives a copy of the line. Before sending the message, set the first word of this buffer to the size, in TCHARs, of the buffer. For ANSI text, this is the number of bytes; for Unicode text, this is the number of characters. The size in the first word is overwritten by the copied line.
Try this instead:
case WM_COMMAND:{
if (LOWORD(wParam) == Calculate) {
int A = 0;
TCHAR textread[256];
*((LPWORD)&textread) = 256; // <-- add this
SendMessage(Box1, EM_GETLINE, 0, (LPARAM)textread);
_stscanf(textread, _T("%d"), &A);
_stprintf(textread, _T("%d"), A);
SendMessage(Box1, WM_SETTEXT, 0, (LPARAM)textread);
}
break;
I think you have several problems there.
First, you didn't show us what Parse1 is. Beware that you must set the size of the buffer in the first word of the buffer. Also, why do you pass 1 as the WPARAM? This is the zero-based index of the line to retrieve from a multiline edit control, but is ignored if the edit is single line.
Also, what is with the first itoa call?
Here is an example that works:
TCHAR textread[256] = {0};
*(reinterpret_cast<WORD*>(&textread)) = 256;
::SendMessage(hwnd, EM_GETLINE, 0, reinterpret_cast<LPARAM>(&textread));
auto n = _ttoi(textread);
_itot_s(n, textread, 256, 10);
::SendMessage(hwnd, WM_SETTEXT, 0, reinterpret_cast<LPARAM>(&textread));
I'm attempting to use inDesign JSX scripts to insert the following data into a document:
data = [{heading:"Heading 1", content: ["Some content"]},
{heading:"Heading 2", content: ["Some other content with", "Multiple paragraphs"]}]
The data has to be placed into a single TextFrame, but have different styling on the heading and content.
The only way I can see to add the text is in one go via the textFrame.contents variable:
allContent = "";
headingParagraphs = []; // keep track of which paragraphs are headings
paragraph = 0;
for (var i = 0; i < data.length; i++) {
allContent += data.heading + "\r"; // Use a newline to split the paragraph
headingParagraphs.push(paragraph);
paragraph++;
for (var j = 0; j < data.content.length; j++) {
allContent += data.content[j] + "\r"; // Use a newline to split the paragraph
paragraph++;
}
}
textFrame.contents = allContent; // all data is in, but all text is styled the same
Then once the data is in, I iterate the paragraphs and add some style to the headings:
for (var i = 0; i < textFrame.paragraphs.count(); i++) {
if (headingParagraphs.indexOf(i) != -1) { // this is a heading paragraph
textFrame.paragraphs[i].pointSize = 20;
}
}
This works fine for small data sets that fit on one page, but once the contents gets bigger than the frame, paragraphs only returns visible paragraphs. And if I follow on to a new textFrame, paragraphs get split and the headingParagraphs[] array no longer lines up.
Ideally I'd like to append to the contents and set styles before I append the next content - but the API docs aren't very clear on how you might do that (if at all)
// Pseudo code:
for all sections:
append the heading to the frame, split to next page if needed
style all the *new* paragraphs as headings
for all section contents
append the content to the frame, split to next page if needed
style any *new* paragraphs as normal content
Is there a way to achieve this using either an append function or some other way to assign headings to the right place after content has been added? Perhaps special characters in the content to define style?
Your longer text gets messed up because currently you are working inside a single text frame. As soon as the text runs out of this one frame, you can't refer to them as this frame's "owned" paragraphs anymore. Use parentStory instead, as it points to the whole story, inside one text frame or spanning more than one. It also keeps on working if the text gets overset.
So if you have a starting frame called textFrame, set a new variable story to textFrame.parentStory and use that to add text.
As for adding text to this frame(/story): indeed, there is no fast way to add formatted text. Setting contents only works for long swathes with the same formatting. One way I've used is to write INX formatted text to a temporary file and importing that. It's slow for short fragments, but larger stories (up to several hundreds of pages) can be created very efficiently in Javascript itself, and then importing it into ID is .. well, it aint fast but faster than trying to do it "manually".
The other way is to add contents one paragraph at a time. The trick is to set formatting and add your text to story.insertionPoints[-1]. This, in a particularly handy notation, refers to the very last text insertion point of the story. You can think of an insertion point as "the text cursor"; you can 'apply' formatting to it, and any text added will then have this formatting as well.
Your code snippet reworked to add one data item at a time:
for (var i = 0; i < data.length; i++)
{
story.insertionPoints[-1].pointSize = 20;
story.insertionPoints[-1].contents = data[i].heading + "\r"; // Use a newline to split the paragraph
story.insertionPoints[-1].pointSize = 10;
for (var j = 0; j < data[i].content.length; j++)
{
story.insertionPoints[-1].contents = data[i].content[j] + "\r"; // Use a newline to split the paragraph
}
}
One thing to note is that you cannot temporarily override the pointSize here. If you set it to your larger size, you must also set it back to the original size again (the '10' in my snippet).
Can I convince you to look in to using paragraph styles? With paragraph styles, you'd have something like
hdrStyle = app.activeDocument.paragraphStyles.item("Header");
textStyle = app.activeDocument.paragraphStyles.item("Text");
for (var i = 0; i < data.length; i++)
{
story.insertionPoints[-1].contents = data[i].heading + "\r"; // Use a newline to split the paragraph
story.insertionPoints[-2].appliedParagraphStyle = hdrStyle;
for (var j = 0; j < data[i].content.length; j++)
{
story.insertionPoints[-1].contents = data[i].content[j] + "\r"; // Use a newline to split the paragraph
story.insertionPoints[-2].appliedParagraphStyle = textStyle;
}
}
Note that it's worth here to invert inserting contents and applying formatting. This is so any previous 'temporary' formatting gets cleared; applying a paragraph style this way overrides any and all local overrides. As you have to apply the style to the previous paragraph (the one before the hard return you just inserted), you would use insertionPoints[-2] here.
The advantages of using styles over local formatting are countless. You can apply all formatting you want with a single command, safely remove all local overridden formatting, and change any part of the formatting globally if you are not satisfied with it, rather than having to re-run your script with slightly different settings.
I want to get all label names for properties of ABPerson object. For example: record ABPerson has three phone numbers defined: Mobile, Other, Work. I use labelAtIndex method to get label name but returned string contains needed value wrapped in characters $!!$. Instead of returning just "Mobile" I get these "_$!<" wrap-characters.
I have following code:
//person object points to ABPerson record from addressBook
ABMultiValue *phoneNumbers = [person valueForProperty:kABPhoneProperty];
NSUInteger count = [phoneNumbers count];
for (int i = 0; i < count; i++) {
NSLog(#"Phone numbers label: %# value: %#", [phoneNumbers labelAtIndex:i], [phoneNumbers valueAtIndex:i]);
}
In log I get following:
2012-01-23 01:14:04.234 FixMyAddressBook[3667:707] Phone numbers label: _$!<Mobile>!$_ value: +327382738273
2012-01-23 01:14:04.370 FixMyAddressBook[3667:707] Phone numbers label: _$!<Work>!$_ value: +3293829328
Could someone point me please how can I get label names for properties without special characters?
As far as I'm aware you need to get the localized label for that item, you'll need to make sure you're using the right reference code.
// Grab the right property first
ABMutableMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
CFIndex phoneNumberCount = ABMultiValueGetCount(phoneNumbers);
for(int k = 0; k < phoneNumberCount; k++)
{
//Get phone number label by iterating across this
CFStringRef phoneNumberValue = ABMultiValueCopyValueAtIndex( phoneNumbers, k );
CFStringRef phoneNumberLabel = ABMultiValueCopyLabelAtIndex(phoneNumbers, i);
CFStringRef phoneNumberLocalizedLabel = ABAddressBookCopyLocalizedLabel( phoneNumberLabel );
// converts "_$!<Work>!$_" to "work" and "_$!<Mobile>!$_" to "mobile"
//do whatever you want to do here
//release your references
CFRelease(phoneNumberLocalizedLabel);
CFRelease(phoneNumberValue);
}
I have an attributedString with image attachments on it, and I need to insert text to it without removing the images. The first thing that I'm doing is detecting at what indexes the images are currently attached.
Below is the code that I'm using, but it is not working all of the time, maybe there is a better way?
char charTemp;
for(int i = 0; i < [mutableAttStr.string length]; i++){
charTemp = [mutableAttStr.string characterAtIndex:i];
if (!isalpha(charTemp) && !isspace(charTemp) && !iscntrl(charTemp) && !ispunct(charTemp)) {
// NSLog(#"isAttachment");
[attachmentArrayCharIndex addObject:[NSNumber numberWithInt:i]];
}
}
First, use unichar, not char.
Second, NSTextAttachment.h declares NSAttachmentCharacter which you can use to determine where an attachment is located in the attributed string.