// Copyright (C) 2003-2026, Foxit Software Inc..
// All Rights Reserved.
//
// http://www.foxitsoftware.com
//
// The following code is copyrighted and contains proprietary information and trade secrets of Foxit Software Inc..
// You cannot distribute any part of Foxit PDF SDK to any third party or general public,
// unless there is a separate license agreement with Foxit Software Inc. which explicitly grants you such rights.
//
// This file contains an example to demonstrate how to use Foxit PDF SDK to add various annotations to PDF document.


#include "FSPDFObjC.h"

NSString *input_path = @"../input_files/";
NSString *output_path = @"../output_files/";

NSString* sn = @"bPxThFlBAYifO3yiW0C51bKbjPap1zHaf5aG5sX378TjFvB7Q0802A==";
NSString* key = @"8f3g1sGNtR8NAgfSNv+BvaJWy2fnrw36NZvzh8GUxYXvs+/YczAk4e34yqlOnmL4asgxGMO7+rlOcSHUSSKagx5g4G7VEXfkYLXnDDx77FOOedZPrFFcOCu1vT4+wOKzy1zkORq9cKtiFf44byH5sfRqf+OvELjep2teT9eF9yPCsSw2vRKljXlPy40DMP9XX1O5OTe+mSG3RvwKUMb0+RpG3YobM87j+/ynTDlJMMXw4vgwuTb1ZuAtlvkTdFz7HDLV81C6TYnn73ddHeGD3qYWBVsD4uJkDwyyH/SWr7QX0HSgVg8HSZqnab1VGdAUYxKY2vGWeOTJdu6qDGb5ZEb9O3kZZg+9LYAmUKzDfCYwfIsYZ8Y9LPC4wMx70kIq7JpNnzPvigrdshV8/ew1F0+qP/P5Z1EB53vDVrp2LVSuL873Wv4g3PzjZlNH+1qgT87hC+Buto4qsSUfP5Y2z0uApu+c/TfttCXbeMLSsw9TY1HQD3mkrZExMaQqRrAuXAcZWdvBnVuG3DCZmm8q0DLxJiCfYfViAU/AkbeKMIGaTJdrvIXBcssfde4nmU6qr0M4x4+Hs2ESddtY2QRtLAUBq/7h7GJlJHkEZr8ueaUy/6D/2vvAWz6wMLgmjlPbDTLqzfnCJylHCPtcJmu1SPPT9v1VreBX3+zNWcIT8HueyHEiUniqzwWkRKaotrnNb/zhnHLPpgaBSwKjyi8rOzzVwu/nY84G9ye4jsVjmkIRItKDrW7z22iS+QQuTwfqLVuMB0OD4jMkPCC2slzPfEeZnuh4+Rewln2qLRJVgI72zJ20OBWAelGSpO1Ii2Y3gOvojdmtUwx6R3Z1qFNWTTB25o9ytcux8BLOtTCkA8T8xaT4N339OTCsu/TmfahIDixKvr8cDa6F2WkBT8SOfv64W9PgiNv5B/BMOD2VWYaAl0N7yD0NkYYg/cDWRC4dfpdeip1jrr0k3mND0oSpIkxC+FicZbaYYwRdtJ9OSVWJ5OE0voLv8HgLze8mw6s4TrN3z+a2NQCveMa2VRN7YcEF7agPrvb/qU+otMwHae/wM7+f+HFAaOW+WTfzfxIVFB8/A1DN0NiEX+em4G7nO5F5ZcvfYPpaaioe8Nn33BbVLtMjXqsOBeM8AXiVfpD6YO75j7BqnBUPnivvD8BxJaaIQZvVSuQmvGm0ynt03IYwE8Rq+jYsunvsZ86jh5BiUR+Nm7sK0Qe9BdZn/7jdqohMv9czfMGUAscX+xBMunFbDpcRbWVpUADcm209L8Ndek2XY7YlCMxPgPVNvfWRF2jxehib9Tpd7zB5ZIDfAEH9zrpLfp29DLvCh2Yx8mH7xxdKG1O9Q0GdHphYHhej6smAcPm68R0GUQaTOLfXqNpueGJC1GAOI3Y4swjyt7jMTWcibnKLzwukWE5rnEDhn5n64JnyUM0ZFkRmtOiV";
@interface MyIconProvider : NSObject<FSIconProviderCallback>
{
    @private
    BOOL use_dynamic_stamp_;
    NSString* icon_file_folder_;
}
-(id)init;
-(id)initWithPath:(NSString*)icon_file_folder;
-(void)setUseDynamicStamp:(BOOL)use_dynamic_stamp;
@end

@implementation MyIconProvider
-(id)init {
    use_dynamic_stamp_ = NO;
    icon_file_folder_ = @"";
    return self;
}

-(id)initWithPath:(NSString*)icon_file_folder{
    icon_file_folder_ = icon_file_folder;
    use_dynamic_stamp_ = NO;
    return self;
}

// If one icon provider offers different style icon for one icon name of a kind of annotaion,
// please use different provider ID or version in order to distinguish different style for Foxit PDF SDK.
// Otherwise, only the first style icon for the same icon name of same kind of annotation will have effect.
-(NSString*)getProviderID {
    if (use_dynamic_stamp_)
        return @"Simple Demo Dynamic MyIconProvider";
    else
        return @"Simple Demo MyIconProvider";
}

-(NSString*)getProviderVersion {
    return @"1.0.0";
}

-(BOOL)hasIcon:(FSAnnotType)annot_type icon_name:(NSString *)icon_name {
    NSString* icon_file_path = @"";
    if (use_dynamic_stamp_)
        icon_file_path = [icon_file_folder_ stringByAppendingPathComponent:@"DynamicStamps"];
    else
        icon_file_path = [icon_file_folder_ stringByAppendingPathComponent:@"StaticStamps"];
    icon_file_path = [icon_file_path stringByAppendingPathComponent:icon_name];
    icon_file_path = [icon_file_path stringByAppendingString:@".pdf"];
    FSPDFDoc* doc = [[FSPDFDoc alloc] initWithPath:icon_file_path];
    FSErrorCode error_code = [doc load:nil];
    if (error_code != FSErrSuccess) {
        NSLog(@"Fail to load icon file:%@, with error value: %ld", icon_file_path, error_code);
        return NO;
    }
    return ![doc isEmpty];
}

-(BOOL)canChangeColor:(FSAnnotType)annot_type icon_name:(NSString *)icon_name {
    return NO;
}

-(FSPDFPage*)getIcon:(FSAnnotType)annot_type icon_name:(NSString *)iconName color:(unsigned int)color annot_dict:(FSPDFDictionary*)annot_dict {
    NSString* icon_file_path = @"";
    if (use_dynamic_stamp_)
        icon_file_path = [icon_file_folder_ stringByAppendingPathComponent:@"DynamicStamps"];
    else
        icon_file_path = [icon_file_folder_ stringByAppendingPathComponent:@"StaticStamps"];
    icon_file_path = [icon_file_path stringByAppendingPathComponent:iconName];
    icon_file_path = [icon_file_path stringByAppendingString:@".pdf"];

    FSPDFDoc* doc = [[FSPDFDoc alloc] initWithPath:icon_file_path];
    FSErrorCode error_code = [doc load:nil];
    if (error_code != FSErrSuccess) {
        NSLog(@"Fail to load icon file:%@, with error value: %ld", icon_file_path, error_code);
        return nil;
    }
    return [doc getPage:0];
}

-(FSShadingColor*)getShadingColor:(FSAnnotType)annot_type icon_name:(NSString *)icon_name referenced_color:(unsigned int)referenced_color shading_index:(int)shading_index {
    return nil;
}

-(NSNumber*)getDisplayWidth:(FSAnnotType)annot_type icon_name:(NSString *)icon_name {
    return [NSNumber numberWithFloat:0.0f];
}

-(NSNumber*)getDisplayHeight:(FSAnnotType)annot_type icon_name:(NSString *)icon_name {
    return [NSNumber numberWithFloat:0.0f];
}

-(void)setUseDynamicStamp:(BOOL)use_dynamic_stamp {
    use_dynamic_stamp_ = use_dynamic_stamp;
}

@end

@interface MyActionEventHandler : NSObject<FSActionCallback>
-(id)init;
@end

@implementation MyActionEventHandler

-(id)init {
    return self;
}

-(id)initWithDocument: (FSPDFDoc *)document{
    current_doc_ = document;
    return self;
}


-(BOOL)invalidateRect:(FSPDFDoc *)document page_index:(int)page_index pdf_rect:(FSRectF *)pdf_rect {
    return NO;
}

-(int)getCurrentPage:(FSPDFDoc *)document {
    return -1;
}

-(void)setCurrentPage:(FSPDFDoc *)document page_index:(int)page_index {}

-(void)setCurrentPage:(FSPDFDoc*)document destination:(FSDestination*)destination {}

-(FSRotation)getPageRotation:(FSPDFDoc *)document page_index:(int)page_index {
    return FSRotation0;
}

-(BOOL)setPageRotation:(FSPDFDoc *)document page_index:(int)page_index rotation:(FSRotation)rotation {
    return NO;
}

-(BOOL)executeNamedAction:(FSPDFDoc *)document named_action:(NSString *)named_action {
    return NO;
}

-(BOOL)setDocChangeMark:(FSPDFDoc *)document change_mark:(BOOL)change_mark {
    return NO;
}

-(BOOL)getDocChangeMark:(FSPDFDoc *)document {
    return NO;
}

-(int)getOpenedDocCount {
    return -1;
}

-(FSPDFDoc*)getOpenedDoc:(int)index {
    return current_doc_;
}

-(FSPDFDoc*)getCurrentDoc {
    return current_doc_;
}

-(FSPDFDoc*)createBlankDoc {
    return nil;
}

-(void)closeDoc:(FSPDFDoc*)document is_prompt_to_save:(BOOL)is_prompt_to_save {}

-(FSPDFDoc*)openDoc: (NSString *)file_path password:(NSString *)password{
    return nil;
}

-(BOOL)beep:(int)type {
    return NO;
}

-(NSString*)response:(NSString *)question title:(NSString *)title default_value:(NSString *)default_value label:(NSString *)label is_password:(BOOL)is_password {
    return @"";
}

-(NSString*)getFilePath:(FSPDFDoc *)document {
    return @"";
}

-(BOOL)isLocalFile:(FSPDFDoc*)document {
    return NO;
}

-(NSString*)getAttachmentsFilePath:(FSPDFDoc*)pdf_doc name:(NSString*)name {
    return @"";
}

-(NSString*)getExtractedEmbeddedFilePath:(FSPDFDoc*)pdf_doc name:(NSString*)name {
    return @"";
}

-(BOOL)print:(FSPDFDoc *)document is_ui:(BOOL)is_ui page_range:(FSRange *)page_range is_silent:(BOOL)is_silent is_shrunk_to_fit:(BOOL)is_shrunk_to_fit is_printed_as_image:(BOOL)is_printed_as_image is_reversed:(BOOL)is_reversed is_to_print_annots:(BOOL)is_to_print_annots {
    return NO;
}

-(BOOL)print:(FSPDFDoc*)document print_params:(FSPrintParams*)print_params {
    return NO;
}

-(BOOL)submitForm:(FSPDFDoc *)document form_data:(NSData *)form_data url:(NSString *)url file_format_type:(FSFileFormatType)file_format_type{
    return NO;
}

-(BOOL)launchURL:(NSString *)url {
    return NO;
}

-(NSString*)browseFile {
    return @"";
}

-(NSString*)browseFile:(BOOL)is_open_dialog file_format:(NSString*)file_format file_filter:(NSString*)file_filter {
    return @"";
}

-(FSActionCallbackLanguage)getLanguage {
    return FSActionCallbackLanguageCHS;
}

-(int)alert:(NSString *)msg title:(NSString *)title type:(int)type icon:(int)icon {
    return 0;
}

-(FSIdentityProperties*)getIdentityProperties {
    return [[FSIdentityProperties alloc] initWithCorporation:@"foxitsoftware" email:@"simple_demo@foxitsoftware.cn" login_name:@"simple demo" name:@"Simple" first_name:@"simple" last_name:@"demo" title:@"developer" department:@"gsdk"];
}

-(BOOL)setIdentityProperties:(FSIdentityProperties*)identity_properties {
    return NO;
}

-(NSString*)popupMenu:(FSMenuListArray *)menus is_selected_item:(NSNumber**)is_selected_item{
    return @"";
}

-(FSMenuItemEx*)popupMenuEx:(FSMenuItemExArray *)menus is_selected_item:(NSNumber**)is_selected_item{
    return [[FSMenuItemEx alloc] init];
}

-(NSString*)getAppInfo:(FSActionCallbackAppInfoType)type {
    return @"";
}

-(BOOL)mailData:(void *)data data_type:(FSActionCallbackMailType)data_type is_ui:(BOOL)is_ui to:(NSString *)to subject:(NSString *)subject cc:(NSString *)cc bcc:(NSString *)bcc message:(NSString *)message {
    return NO;
}

-(unsigned int)verifySignature:(FSPDFDoc*)document pdf_signature:(FSSignature*)pdf_signature {
    return FSSignatureStateVerifyErrorData;
}

-(NSString*)getUntitledBookmarkName {
    return @"Untitled";
}

-(NSArray<NSString*>*)getPrinterNameList {
    return [NSArray array];
}

-(BOOL)addToolButton:(FSButtonItem*)button_item {
    return NO;
}

-(BOOL)removeToolButtom:(NSString*)button_name {
    return NO;
}

-(FSMenuListArray*) getMenuItemNameList {
    return [[FSMenuListArray alloc] init];
}

-(BOOL) addMenuItem:(FSMenuItemConfig*)menu_item_config is_prepend:(BOOL)is_prepend {
    return NO;
}

-(BOOL) addSubMenu:(FSMenuItemConfig*)menu_item_config {
    return NO;
}

-(BOOL) showDialog:(FSDialogDescriptionConfig*)dlg_config {
    return NO;
}

-(BOOL) getFullScreen {
    return NO;
}

-(void) setFullScreen:(BOOL)is_full_screen {
    
}

-(void) onFieldValueChanged:(NSString*)field_name type:(FSActionCallbackJSFieldValueChangeType)type value_before_changed:(NSArray<NSString*>*)value_before_changed value_after_changed:(NSArray<NSString*>*)value_after_changed {

}

-(void)updateLogicalLabel {}

-(FSActionCallbackJsMailResult)mailDoc:(FSPDFDoc*)document to_address:(NSString*)to_address cc_address:(NSString*)cc_address bcc_address:(NSString*)bcc_address subject:(NSString*)subject message:(NSString*)message is_ui:(BOOL)is_ui {
    return FSActionCallbackJSMailResultFailed;
}

-(NSString*)getTemporaryFileName:(FSPDFDoc*)document file_name:(NSString*)file_name {
    return @"";
}

-(id<FSMediaPlayerCallback>) openMediaPlayer:(FSPlayerArgs*)player_args{
   return NULL;
}

-(NSString*)getTemporaryDirectory {
   return @"";
}

 -(void)scroll:(FSPointF*)point { }

 -(void)selectPageNthWord:(int)page_index start_offset:(int)start_offset end_offset:(int)end_offset is_show_selection:(BOOL)is_show_selection { }

-(FSPointF*)getMousePosition {
    return [[FSPointF alloc] init];
}

-(FSRectF*)getPageWindowRect: (FSPDFDoc*)document page_index:(int)page_index {
    return [[FSRectF alloc] init];
}

-(FSActionCallbackLayoutMode)getLayoutMode {
    return FSActionCallbackLayoutModeSinglePage;
}

-(void)setLayoutMode:(FSActionCallbackLayoutMode)layout_mode is_cover_mode:(BOOL)is_cover_mode { }

-(float)getPageScale {
    return 0.0;
}

-(void)setPageScale:(FSDestinationZoomMode)zoom_mode dest:(FSDestination*)dest { }

-(FSDestinationZoomMode)getPageZoomMode {
    return FSDestinationZoomXYZ;   
}
-(void)query:(NSString*)keywords search_scope:(FSActionCallbackSearchScope)search_scope search_option:(FSSearchOption*)search_opion di_path:(NSString*)di_path{}

-(FSSearchIndexConfig*) addSearchIndex:(NSString*)di_path selected:(bool)is_selected{return [[FSSearchIndexConfig alloc] init];}

-(bool)removeSearchIndex:(FSSearchIndexConfig*)search_index_config{return NO;}

-(NSArray<NSString*>*)getSignatureAPStyleNameList { return [NSArray array];}

-(FSSOAPResponseInfo*)soapRequest:(FSSOAPRequestProperties*)request_params{return [[FSSOAPResponseInfo alloc] init];}

-(void) enablePageLoop:(BOOL)is_loop{}

-(BOOL) isPageLoop{return NO;}

-(void) setDefaultPageTransitionMode:(NSString*)trans_type trans_di:(NSString*)trans_di{}

-(BOOL) isCurrentDocOpenedInBrowser{return NO;}

-(void) postMessageToHtml:(NSArray<NSString*>*)message{}

-(void) notifyBeginDoJob:(FSPDFDoc*)document event_type:(FSJavascriptModifyItemInfoJavascriptEventType)event_type{}

-(void) notifyAfterDataChange:(FSPDFDoc*)document modify_item_info:(FSJavascriptModifyItemInfo*)modify_item_info{}

-(void) notifyEndDoJob:(FSPDFDoc*)document event_type:(FSJavascriptModifyItemInfoJavascriptEventType)event_type{}

-(BOOL) initModifyItem:(FSPDFDoc*)document item_type:(FSActionCallbackModifyItemType)item_type page_index:(int)page_index dict_name:(NSString*)dict_name{
    return YES;
}
-(void) resetModifyItem:(FSPDFDoc*)document{}

-(int) getVisiblePageCount:(FSPDFDoc*)document { return 0;}

-(int) getVisiblePage:(FSPDFDoc*)document index:(int)index{ return -1;}

FSPDFDoc* current_doc_;
@end


FSDateTime* getLocalDateTime() {
    time_t t = time(NULL);
    struct tm* rime = localtime(&t);
    tzset();
    int timezone_hour = (int)timezone / 3600 * -1;
    int timezone_minute = (abs((int)timezone) % 3600) / 60;

    FSDateTime* datetime = [[FSDateTime alloc] initWithYear:(rime->tm_year + 1900) month:(rime->tm_mon + 1) day:(rime->tm_mday) hour:(rime->tm_hour) minute:(rime->tm_min) second:(rime->tm_sec) milliseconds:0 utc_hour_offset:timezone_hour utc_minute_offset:timezone_minute];
    
    return datetime;
}

NSString* randomUID() {
    NSString* uuid = @"";
    const char* c = "0123456789qwertyuiopasdfghjklzxcvbnm";
    
    for (int n = 0; n < 16; n++) {
        NSString* uuid_temp = @"";
        int b = rand() % 255;
        switch (n) {
            case 6:
                uuid_temp = [NSString stringWithFormat:@"4%x", b % 15];
                break;
            case 8:
                uuid_temp = [NSString stringWithFormat:@"%c%x", c[rand() % strlen(c)], b % 15];
                break;
            default:
                uuid_temp = [NSString stringWithFormat:@"%02x", b];
                break;
        }
        uuid  = [uuid stringByAppendingString:uuid_temp];
        
        switch (n) {
            case 3:
            case 5:
            case 7:
            case 9:
                uuid = [uuid stringByAppendingString:@"-"];
                break;
        }
    }
    return uuid;
}

void addAnnotations(FSPDFPage* page)
{
    {
        // Add line annotation
        // No special intent, as a common line.
        FSRectF* annot_rect = [[FSRectF alloc] initWithLeft1:0 bottom1:650 right1:100 top1:750];
        FSLine* line = [[FSLine alloc] initWithAnnot:[page addAnnot:FSAnnotLine rect:annot_rect]];
        //This flag is used for printing annotations.
        [line setFlags:4];
        FSPointF* point = [FSPointF new];
        [point set:20 y:650];
        [line setStartPoint:point];
        [point set:100 y:740];
        [line setEndPoint:point];
        // Intent, as line arrow.
        [line setContent:@"A line arrow annotation"];
        [line setIntent:@"LineArrow"];
        [line setSubject:@"Arrow"];
        [line setTitle:@"Foxit SDK"];
        FSDateTime* local_time = getLocalDateTime();
        [line setCreationDateTime:local_time];
        [line setModifiedDateTime:local_time];
        [line setUniqueID:randomUID()];
        // Appearance should be reset.
        [line resetAppearanceStream];
        
        annot_rect = [[FSRectF alloc] initWithLeft1:0 bottom1:650 right1:100 top1:760];
        line = [[FSLine alloc] initWithAnnot:[page addAnnot:FSAnnotLine rect:annot_rect]];
        //This flag is used for printing annotations.
        [line setFlags:4];
        // Set foxit RGB color
        [line setBorderColor:0x00FF00];
        [point set:10 y:650];
        [line setStartPoint:point];
        [point set:100 y:750];
        [line setEndPoint:point];
        [line setContent:@"A common line."];
        [line setLineStartStyle:FSMarkupEndingStyleSquare];
        [line setLineEndStyle:FSMarkupEndingStyleOpenArrow];
        // Show text in line
        [line enableCaption:YES];
        [point set:0 y:5];
        [line setCaptionOffset:point];
        
        [line setSubject:@"Line"];
        [line setTitle:@"Foxit SDK"];
        local_time = getLocalDateTime();
        [line setCreationDateTime:local_time];
        [line setModifiedDateTime:local_time];
        [line setUniqueID:randomUID()];
        // Appearance should be reset.
        [line resetAppearanceStream];
        NSLog(@"Add a line annotations.");
    }
    
    {
        // Add circle annotation
        FSRectF* annot_rect = [[FSRectF alloc] initWithLeft1:100 bottom1:650 right1:200 top1:750];
        FSCircle* circle = [[FSCircle alloc] initWithAnnot:[page addAnnot:FSAnnotCircle rect:annot_rect]];
        FSRectF* inner_rect = [[FSRectF alloc] initWithLeft1:120 bottom1:660 right1:160 top1:740];
        //This flag is used for printing annotations.
        [circle setFlags:4];
        [circle setInnerRect:inner_rect];
        [circle setSubject:@"Circle"];
        [circle setTitle:@"Foxit SDK"];
        FSDateTime* local_time = getLocalDateTime();
        [circle setCreationDateTime:local_time];
        [circle setModifiedDateTime:local_time];
        [circle setUniqueID:randomUID()];
        // Appearance should be reset.
        [circle resetAppearanceStream];
        NSLog(@"Add a circle annotation.");
    }
    
    {
        // Add square annotation
        FSRectF* annot_rect = [[FSRectF alloc] initWithLeft1:200 bottom1:650 right1:300 top1:750];
        FSSquare* square = [[FSSquare alloc] initWithAnnot:[page addAnnot:FSAnnotSquare rect:annot_rect]];
        //This flag is used for printing annotations.
        [square setFlags:4];
        [square setFillColor:0x00FF00];
        FSRectF* inner_rect = [[FSRectF alloc] initWithLeft1:220 bottom1:660 right1:260 top1:740];
        [square setInnerRect:inner_rect];
        [square setSubject:@"Square"];
        [square setTitle:@"Foxit SDK"];
        FSDateTime* local_time = getLocalDateTime();
        [square setCreationDateTime:local_time];
        [square setModifiedDateTime:local_time];
        [square setUniqueID:randomUID()];
        // Appearance should be reset.
        [square resetAppearanceStream];
        NSLog(@"Add a square annotation.");
    }
    
    {
        // Add polygon annotation, as cloud.
        FSRectF* annot_rect = [[FSRectF alloc] initWithLeft1:300 bottom1:650 right1:500 top1:750];
        FSPolygon* polygon = [[FSPolygon alloc] initWithAnnot:[page addAnnot:FSAnnotPolygon rect:annot_rect]];
        //This flag is used for printing annotations.
        [polygon setFlags:4];
        [polygon setIntent:@"PolygonCloud"];
        [polygon setFillColor:0x0000FF];
        FSPointFArray* vertex_array = [FSPointFArray new];
        FSPointF* point = [FSPointF new];
        [point set:335 y:665];
        [vertex_array add:point];
        [point set:365 y:665];
        [vertex_array add:point];
        [point set:385 y:705];
        [vertex_array add:point];
        [point set:365 y:740];
        [vertex_array add:point];
        [point set:335 y:740];
        [vertex_array add:point];
        [point set:315 y:705];
        [vertex_array add:point];
        [polygon setVertexes:vertex_array];
        [polygon setSubject:@"Cloud"];
        [polygon setTitle:@"Foxit SDK"];
        FSDateTime* local_time = getLocalDateTime();
        [polygon setCreationDateTime:local_time];
        [polygon setModifiedDateTime:local_time];
        [polygon setUniqueID:randomUID()];
        // Appearance should be reset.
        [polygon resetAppearanceStream];
        NSLog(@"Add a polygon annotation.");
    }
    
    {
        // Add polygon annotation, with dashed border.
        FSFloatArray* dash_array = [FSFloatArray new];
        [dash_array setSize:2 nGrowBy:-1];
        [dash_array setAt:0 newElement:2];
        [dash_array setAt:1 newElement:2];
        FSBorderInfo* borderinfo = [[FSBorderInfo alloc] initWithWidth:2.0 style:FSBorderInfoDashed intensity:2.0 dash_phase:3.0 dashes:dash_array];
        
        FSRectF* annot_rect = [[FSRectF alloc] initWithLeft1:400 bottom1:650 right1:500 top1:750];
        FSPolygon* polygon = [[FSPolygon alloc] initWithAnnot:[page addAnnot:FSAnnotPolygon rect:annot_rect]];
        //This flag is used for printing annotations.
        [polygon setFlags:4];
        [polygon setFillColor:0x0000FF];
        [polygon setBorderInfo:borderinfo];
        
        FSPointFArray* vertex_array = [FSPointFArray new];
        FSPointF* point = [FSPointF new];
        [point set:435 y:665];
        [vertex_array add:point];
        [point set:465 y:665];
        [vertex_array add:point];
        [point set:485 y:705];
        [vertex_array add:point];
        [point set:465 y:740];
        [vertex_array add:point];
        [point set:435 y:740];
        [vertex_array add:point];
        [point set:415 y:705];
        [vertex_array add:point];
        [polygon setVertexes:vertex_array];
        
        [polygon setSubject:@"Polygon"];
        [polygon setTitle:@"Foxit SDK"];
        FSDateTime* local_time = getLocalDateTime();
        [polygon setCreationDateTime:local_time];
        [polygon setModifiedDateTime:local_time];
        [polygon setUniqueID:randomUID()];
        // Appearance should be reset.
        [polygon resetAppearanceStream];
        NSLog(@"Add a polygon cloud annotation.");
    }
    
    {
        // Add polyline annotation
        FSRectF* annot_rect = [[FSRectF alloc] initWithLeft1:500 bottom1:650 right1:600 top1:750];
        FSPolyLine* polyline = [[FSPolyLine alloc] initWithAnnot:[page addAnnot:FSAnnotPolyLine rect:annot_rect]];
        //This flag is used for printing annotations.
        [polyline setFlags:4];
        FSPointFArray* vertex_array = [FSPointFArray new];
        FSPointF* point = [FSPointF new];
        [point set:515 y:705];
        [vertex_array add:point];
        [point set:535 y:740];
        [vertex_array add:point];
        [point set:565 y:740];
        [vertex_array add:point];
        [point set:585 y:705];
        [vertex_array add:point];
        [point set:565 y:665];
        [vertex_array add:point];
        [point set:535 y:665];
        [vertex_array add:point];
        [polyline setVertexes:vertex_array];
        [polyline setSubject:@"PolyLine"];
        [polyline setTitle:@"Foxit SDK"];
        FSDateTime* local_time = getLocalDateTime();
        [polyline setCreationDateTime:local_time];
        [polyline setModifiedDateTime:local_time];
        [polyline setUniqueID:randomUID()];
        // Appearance should be reset.
        [polyline resetAppearanceStream];
        NSLog(@"Add a polyline annotation.");
    }
    
    {
        // Add freetext annotation, as type writer.
        FSRectF* annot_rect = [[FSRectF alloc] initWithLeft1:10 bottom1:550 right1:200 top1:600];
        FSFreeText* freetext = [[FSFreeText alloc] initWithAnnot:[page addAnnot:FSAnnotFreeText rect:annot_rect]];
        //This flag is used for printing annotations.
        [freetext setFlags:4];
        // Set default appearance
        unsigned int da_flags = FSDefaultAppearanceFlagFont | FSDefaultAppearanceFlagFontSize | FSDefaultAppearanceFlagTextColor;
        FSFont* da_font = [[FSFont alloc] initWithFont_id:FSFontStdIDHelvetica];
        FSDefaultAppearance* default_ap = [[FSDefaultAppearance alloc] initWithFlags:da_flags font:da_font text_size:12.0 text_color:0x000000];
        // Set default appearance for form.
        [freetext setDefaultAppearance:default_ap];
        [freetext setIntent:@"FreeTextTypewriter"];
        [freetext setContent:@"A typewriter annotation"];
        [freetext setSubject:@"FreeTextTypewriter"];
        [freetext setTitle:@"Foxit SDK"];
        FSDateTime* local_time = getLocalDateTime();
        [freetext setCreationDateTime:local_time];
        [freetext setModifiedDateTime:local_time];
        [freetext setUniqueID:randomUID()];
        // Appearance should be reset.
        [freetext resetAppearanceStream];
        NSLog(@"Add a typewriter freetext annotation.");
        
    }
    {
        // Add freetext annotation, as call-out.
        FSRectF* annot_rect = [[FSRectF alloc] initWithLeft1:300 bottom1:550 right1:400 top1:600];
        FSFreeText* freetext = [[FSFreeText alloc] initWithAnnot:[page addAnnot:FSAnnotFreeText rect:annot_rect]];
        //This flag is used for printing annotations.
        [freetext setFlags:4];
        // Set default appearance
        unsigned int da_flags = FSDefaultAppearanceFlagFont | FSDefaultAppearanceFlagFontSize | FSDefaultAppearanceFlagTextColor;
        FSFont* da_font = [[FSFont alloc] initWithFont_id:FSFontStdIDHelveticaB];
        FSDefaultAppearance* default_ap = [[FSDefaultAppearance alloc] initWithFlags:da_flags font:da_font text_size:12.0 text_color:0x000000];
        // Set default appearance for form.
        [freetext setDefaultAppearance:default_ap];
        [freetext setIntent:@"FreeTextCallout"];
        FSPointFArray* callout_points = [FSPointFArray new];
        FSPointF* point = [FSPointF new];
        [point set:250 y:540];
        [callout_points add:point];
        [point set:280 y:570];
        [callout_points add:point];
        [point set:300 y:570];
        [callout_points add:point];
        [freetext setCalloutLinePoints:callout_points];
        [freetext setCalloutLineEndingStyle:FSMarkupEndingStyleOpenArrow];
        
        [freetext setContent:@"A callout annotation."];
        [freetext setSubject:@"FreeTextCallout"];
        [freetext setTitle:@"Foxit SDK"];
        FSDateTime* local_time = getLocalDateTime();
        [freetext setCreationDateTime:local_time];
        [freetext setModifiedDateTime:local_time];
        [freetext setUniqueID:randomUID()];
        // Appearance should be reset.
        [freetext resetAppearanceStream];
        NSLog(@"Add a callout freetext annotation.");
    }
    {
        // Add freetext annotation, as text box.
        FSRectF* annot_rect = [[FSRectF alloc] initWithLeft1:450 bottom1:550 right1:550 top1:600];
        FSFreeText* freetext = [[FSFreeText alloc] initWithAnnot:[page addAnnot:FSAnnotFreeText rect:annot_rect]];
        //This flag is used for printing annotations.
        [freetext setFlags:4];
        // Set default appearance
        unsigned int da_flags = FSDefaultAppearanceFlagFont | FSDefaultAppearanceFlagFontSize | FSDefaultAppearanceFlagTextColor;
        FSFont* da_font = [[FSFont alloc] initWithFont_id:FSFontStdIDHelveticaI];
        FSDefaultAppearance* default_ap = [[FSDefaultAppearance alloc] initWithFlags:da_flags font:da_font text_size:12.0 text_color:0x000000];
        // Set default appearance for form.
        [freetext setDefaultAppearance:default_ap];
        [freetext setContent:@"A text box annotation."];
        [freetext setSubject:@"Textbox"];
        [freetext setTitle:@"Foxit SDK"];
        FSDateTime* local_time = getLocalDateTime();
        [freetext setCreationDateTime:local_time];
        [freetext setModifiedDateTime:local_time];
        [freetext setUniqueID:randomUID()];
        // Appearance should be reset.
        [freetext resetAppearanceStream];
        NSLog(@"Add a text box freetext annotation.");
    }
    {
        // Add highlight annotation.
        FSRectF* annot_rect = [[FSRectF alloc] initWithLeft1:10 bottom1:450 right1:100 top1:550];
        FSHighlight* highlight = [[FSHighlight alloc] initWithAnnot:[page addAnnot:FSAnnotHighlight rect:annot_rect]];
        //This flag is used for printing annotations.
        [highlight setFlags:4];
        [highlight setContent:@"Highlight"];
        FSQuadPoints* quad_points = [FSQuadPoints new];
        FSPointF* point = [FSPointF new];
        [point set:10 y:500];
        quad_points.first = point;
        [point set:90 y:500];
        quad_points.second = point;
        [point set:10 y:480];
        quad_points.third = point;
        [point set:90 y:480];
        quad_points.fourth = point;
        FSQuadPointsArray* quad_points_array = [FSQuadPointsArray new];
        [quad_points_array add:quad_points];
        [highlight setQuadPoints:quad_points_array];
        [highlight setSubject:@"Highlight"];
        [highlight setTitle:@"Foxit SDK"];
        FSDateTime* local_time = getLocalDateTime();
        [highlight setCreationDateTime:local_time];
        [highlight setModifiedDateTime:local_time];
        [highlight setUniqueID:randomUID()];
        // Appearance should be reset.
        [highlight resetAppearanceStream];
        NSLog(@"Add a highlight annotation.");
    }
    {
        // Add underline annotation.
        FSRectF* annot_rect = [[FSRectF alloc] initWithLeft1:100 bottom1:450 right1:200 top1:550];
        FSUnderline* underline = [[FSUnderline alloc] initWithAnnot:[page addAnnot:FSAnnotUnderline rect:annot_rect]];
        //This flag is used for printing annotations.
        [underline setFlags:4];
        FSQuadPoints* quad_points = [FSQuadPoints new];
        FSPointF* point = [FSPointF new];
        [point set:110 y:500];
        quad_points.first = point;
        [point set:190 y:500];
        quad_points.second = point;
        [point set:110 y:480];
        quad_points.third = point;
        [point set:190 y:480];
        quad_points.fourth = point;
        FSQuadPointsArray* quad_points_array = [FSQuadPointsArray new];
        [quad_points_array add:quad_points];
        [underline setQuadPoints:quad_points_array];
        [underline setSubject:@"Underline"];
        [underline setTitle:@"Foxit SDK"];
        FSDateTime* local_time = getLocalDateTime();
        [underline setCreationDateTime:local_time];
        [underline setModifiedDateTime:local_time];
        [underline setUniqueID:randomUID()];
        // Appearance should be reset.
        [underline resetAppearanceStream];
        NSLog(@"Add a underline annotation.");
    }
    {
        // Add squiggly annotation.
        FSRectF* annot_rect = [[FSRectF alloc] initWithLeft1:200 bottom1:450 right1:300 top1:550];
        FSSquiggly* squiggly = [[FSSquiggly alloc] initWithAnnot:[page addAnnot:FSAnnotSquiggly rect:annot_rect]];
        //This flag is used for printing annotations.
        [squiggly setFlags:4];
        [squiggly setIntent:@"Squiggly"];
        FSQuadPoints* quad_points = [FSQuadPoints new];
        FSPointF* point = [FSPointF new];
        [point set:210 y:500];
        quad_points.first = point;
        [point set:290 y:500];
        quad_points.second = point;
        [point set:210 y:480];
        quad_points.third = point;
        [point set:290 y:480];
        quad_points.fourth = point;
        FSQuadPointsArray* quad_points_array = [FSQuadPointsArray new];
        [quad_points_array add:quad_points];
        [squiggly setQuadPoints:quad_points_array];
        [squiggly setSubject:@"Squiggly"];
        [squiggly setTitle:@"Foxit SDK"];
        FSDateTime* local_time = getLocalDateTime();
        [squiggly setCreationDateTime:local_time];
        [squiggly setModifiedDateTime:local_time];
        [squiggly setUniqueID:randomUID()];
        // Appearance should be reset.
        [squiggly resetAppearanceStream];
        NSLog(@"Add a squiggly annotation.");
    }
    {
        // Add strikeout annotation.
        FSRectF* annot_rect = [[FSRectF alloc] initWithLeft1:300 bottom1:450 right1:400 top1:550];
        FSStrikeOut* strikeout = [[FSStrikeOut alloc] initWithAnnot:[page addAnnot:FSAnnotStrikeOut rect:annot_rect]];
        //This flag is used for printing annotations.
        [strikeout setFlags:4];
        FSQuadPoints* quad_points = [FSQuadPoints new];
        FSPointF* point = [FSPointF new];
        [point set:310 y:500];
        quad_points.first = point;
        [point set:390 y:500];
        quad_points.second = point;
        [point set:310 y:480];
        quad_points.third = point;
        [point set:390 y:480];
        quad_points.fourth = point;
        FSQuadPointsArray* quad_points_array = [FSQuadPointsArray new];
        [quad_points_array add:quad_points];
        [strikeout setQuadPoints:quad_points_array];
        [strikeout setSubject:@"StrikeOut"];
        [strikeout setTitle:@"Foxit SDK"];
        FSDateTime* local_time = getLocalDateTime();
        [strikeout setCreationDateTime:local_time];
        [strikeout setModifiedDateTime:local_time];
        [strikeout setUniqueID:randomUID()];
        // Appearance should be reset.
        [strikeout resetAppearanceStream];
        NSLog(@"Add a strikeout annotation.");
    }
    {
        // Add caret annotation.
        FSRectF* annot_rect = [[FSRectF alloc] initWithLeft1:400 bottom1:450 right1:420 top1:470];
        FSCaret* caret = [[FSCaret alloc] initWithAnnot:[page addAnnot:FSAnnotCaret rect:annot_rect]];
        //This flag is used for printing annotations.
        [caret setFlags:4];
        FSRectF* inner_rect = [[FSRectF alloc] initWithLeft1:410 bottom1:450 right1:430 top1:470];
        [caret setInnerRect:inner_rect];
        [caret setContent:@"Caret annotation"];
        [caret setSubject:@"Caret"];
        [caret setTitle:@"Foxit SDK"];
        FSDateTime* local_time = getLocalDateTime();
        [caret setCreationDateTime:local_time];
        [caret setModifiedDateTime:local_time];
        [caret setUniqueID:randomUID()];
        // Appearance should be reset.
        [caret resetAppearanceStream];
        NSLog(@"Add a caret annotation.");
    }
    {
        // Add note annotation
        FSRectF* annot_rect = [[FSRectF alloc] initWithLeft1:10 bottom1:350 right1:50 top1:400];
        FSNote* note = [[FSNote alloc] initWithAnnot:[page addAnnot:FSAnnotNote rect:annot_rect]];
        //This flag is used for printing annotations.
        [note setFlags:4];
        [note setIconName:@"Comment"];
        [note setSubject:@"Note"];
        [note setTitle:@"Foxit SDK"];
        [note setContent:@"Note annotation."];
        FSDateTime* local_time = getLocalDateTime();
        [note setCreationDateTime:local_time];
        [note setModifiedDateTime:local_time];
        [note setUniqueID:randomUID()];
        // Add popup to note annotation
        annot_rect = [[FSRectF alloc] initWithLeft1:300 bottom1:450 right1:500 top1:550];
        FSPopup* popup = [[FSPopup alloc] initWithAnnot:[page addAnnot:FSAnnotPopup rect:annot_rect]];
        [popup setBorderColor:0x00FF00];
        [popup setOpenStatus:NO];
        local_time = getLocalDateTime();
        [popup setModifiedDateTime:local_time];
        [note setPopup:popup];
        
        // Add reply annotation to note annotation
        FSNote* reply = [note addReply];
        [reply setContent:@"reply"];
        local_time = getLocalDateTime();
        [reply setModifiedDateTime:local_time];
        [reply setTitle:@"Foxit SDK"];
        [reply setUniqueID:randomUID()];
        
        // Add state annotation to note annotation
        FSNote* state = [note addStateAnnot:@"Foxit SDK" model:FSMarkupStateModelReview state:FSMarkupStateAccepted];
        [state setContent:@"Accepted set by Foxit SDK"];
        [state setUniqueID:randomUID()];
        // Appearance should be reset.
        [note resetAppearanceStream];
        NSLog(@"Add a note annotation.");
    }
    {
        // Add ink annotation
        FSRectF* annot_rect = [[FSRectF alloc] initWithLeft1:100 bottom1:350 right1:200 top1:450];
        FSInk* ink = [[FSInk alloc] initWithAnnot:[page addAnnot:FSAnnotInk rect:annot_rect]];
        //This flag is used for printing annotations.
        [ink setFlags:4];
        FSPath* inklist = [FSPath new];
        float width = 100;
        float height = 100;
        float out_width = MIN(width, height) * 2 / 3.f;
        float inner_width = out_width * sin(18.f / 180.f * 3.14f) / sin(36.f / 180.f * 3.14f);
        FSPointF* center = [FSPointF new];
        [center set:150 y:400];
        float x = out_width;
        float y = 0;
        FSPointF* point = [FSPointF new];
        [point set:(center.x + x) y:(center.y + y)];
        [inklist moveTo:point];
        for (int i = 0; i < 5; i++) {
            x = out_width * cos(72.f * i / 180.f * 3.14f);
            y = out_width * sin(72.f * i / 180.f * 3.14f);
            [point set:(center.x + x) y:(center.y + y)];
            [inklist lineTo:point];
            
            x = inner_width * cos((72.f * i + 36) / 180.f * 3.14f);
            y = inner_width * sin((72.f * i + 36) / 180.f * 3.14f);
            [point set:(center.x + x) y:(center.y + y)];
            [inklist lineTo:point];
        }
        [point set:(center.x + out_width) y:(center.y + 0)];
        [inklist lineTo:point];
        [inklist closeFigure];
        [ink setInkList:inklist];
        [ink setSubject:@"Ink"];
        [ink setTitle:@"Foxit SDK"];
        [ink setContent:@"Note annotation."];
        FSDateTime* local_time = getLocalDateTime();
        [ink setCreationDateTime:local_time];
        [ink setModifiedDateTime:local_time];
        [ink setUniqueID:randomUID()];
        // Appearance should be reset.
        [ink resetAppearanceStream];
        NSLog(@"Add an ink annotation.");
    }
    {
        // Add file attachment annotation
        NSString* pdf_path = [input_path stringByAppendingPathComponent:@"AboutFoxit.pdf"];
        FSRectF* annot_rect = [[FSRectF alloc] initWithLeft1:280 bottom1:350 right1:300 top1:380];
        FSFileAttachment* file_attachment = [[FSFileAttachment alloc] initWithAnnot:[page addAnnot:FSAnnotFileAttachment rect:annot_rect]];
        [file_attachment setIconName:@"Graph"];
        //This flag is used for printing annotations.
        [file_attachment setFlags:4];
        FSFileSpec* file_spec = [[FSFileSpec alloc] initWithDocument:[page getDocument]];
        [file_spec setFileName:@"attachment.pdf"];
        FSDateTime* local_time = getLocalDateTime();
        [file_spec setCreationDateTime:local_time];
        [file_spec setDescription:@"The original file"];
        [file_spec setModifiedDateTime:local_time];
        [file_spec embed:pdf_path];
        [file_attachment setFileSpec:file_spec];
        [file_attachment setSubject:@"File Attachment"];
        [file_attachment setTitle:@"Foxit SDK"];
        // Appearance should be reset.
        [file_attachment resetAppearanceStream];
        NSLog(@"Add an attachment annotation.");
    }
    {
        // Add link annotation
        FSRectF* annot_rect = [[FSRectF alloc] initWithLeft1:350 bottom1:350 right1:380 top1:400];
        FSLink* link = [[FSLink alloc] initWithAnnot:[page addAnnot:FSAnnotLink rect:annot_rect]];
        //This flag is used for printing annotations.
        [link setFlags:4];
        [link setHighlightingMode:FSAnnotHighlightingPush];
        
        // Add action for link annotation
        FSPDFDoc* doc = [page getDocument];
        FSURIAction* action = [[FSURIAction alloc] initWithAction:[FSAction create:doc action_type:FSActionTypeURI]];
        [action setTrackPositionFlag:YES];
        [action setURI:@"www.foxitsoftware.com"];
        [link setAction:action];
        // Appearance should be reset.
        [link resetAppearanceStream];
        NSLog(@"Add a link annotation.");
    }
    {
        // Set icon provider for annotation to Foxit PDF SDK.
        NSString* icon_folder = [input_path stringByAppendingPathComponent:@"Stamps"];
        MyIconProvider* icon_provider = [[MyIconProvider alloc] initWithPath:icon_folder];
        [icon_provider setUseDynamicStamp:NO];
        [FSLibrary setAnnotIconProviderCallback:icon_provider];
        
        // Add common stamp annotation.
        [FSLibrary setActionCallback:nil];
        
        FSRectF* annot_rect = [[FSRectF alloc] initWithLeft1:110 bottom1:150 right1:200 top1:250];
        FSStamp* static_stamp = [[FSStamp alloc] initWithAnnot:[page addAnnot:FSAnnotStamp rect:annot_rect]];
        [static_stamp setIconName:@"Approved"];
        //This flag is used for printing annotations.
        [static_stamp setFlags:4];
        // Appearance should be reset.
        [static_stamp resetAppearanceStream];
        
        // Add dynamic stamp annotation.
        FSPDFDoc* doc = [page getDocument];
        [FSLibrary setActionCallback:[[MyActionEventHandler alloc] initWithDocument:doc]];
        [icon_provider setUseDynamicStamp:YES];
        
        annot_rect = [[FSRectF alloc] initWithLeft1:10 bottom1:150 right1:100 top1:250];
        FSStamp* dynamic_stamp = [[FSStamp alloc] initWithAnnot:[page addAnnot:FSAnnotStamp rect:annot_rect]];
        //This flag is used for printing annotations.
        [dynamic_stamp setFlags:4];
        [dynamic_stamp setIconName:@"Approved"];
        // Appearance should be reset.
        [dynamic_stamp resetAppearanceStream];
        NSLog(@"Add stamp annotations.");
    }
    {
        // Add freetext annotation with richtext, as type writer.
        FSRectF* annot_rect = [[FSRectF alloc] initWithLeft1:10 bottom1:50 right1:200 top1:100];
        FSFreeText* freetext = [[FSFreeText alloc] initWithAnnot:[page addAnnot:FSAnnotFreeText rect:annot_rect]];
        //This flag is used for printing annotations.
        [freetext setFlags:4];
        // Set default appearance
        unsigned int da_flags = FSDefaultAppearanceFlagFont | FSDefaultAppearanceFlagFontSize | FSDefaultAppearanceFlagTextColor;
        FSFont* da_font = [[FSFont alloc] initWithFont_id:FSFontStdIDHelvetica];
        FSDefaultAppearance* default_ap = [[FSDefaultAppearance alloc] initWithFlags:da_flags font:da_font text_size:12.0 text_color:0x000000];
        // Set default appearance for form.
        [freetext setDefaultAppearance:default_ap];
        [freetext setIntent:@"FreeTextTypewriter"];
        [freetext setContent:@"A typewriter annotation"];
        [freetext setSubject:@"FreeTextTypewriter"];
        [freetext setTitle:@"Foxit SDK"];
        FSDateTime* local_time = getLocalDateTime();
        [freetext setCreationDateTime:local_time];
        [freetext setModifiedDateTime:local_time];
        [freetext setUniqueID:randomUID()];

        FSRichTextStyle* richtext_style = [[FSRichTextStyle alloc] init];
        FSFont* rcstyle_font_1 = [[FSFont alloc] initWithName:@"Times New Roman" styles:0 charset:FSFontCharsetANSI weight:0];
        [richtext_style setFont:rcstyle_font_1];
        [richtext_style setText_color:0xFF0000];
        [richtext_style setText_size:10];
        [freetext addRichText:@"Typewriter annotation " style:richtext_style];

        [richtext_style setText_color:0x00FF00];
        [richtext_style setIs_underline:YES];
        [freetext addRichText:@"1-underline " style:richtext_style];
        
        [richtext_style setIs_underline:NO];
        [richtext_style setText_color:0x0000FF];
        [richtext_style setIs_strikethrough:YES];
        FSFont* rcstyle_font_2 = [[FSFont alloc] initWithName:@"Calibri" styles:0 charset:FSFontCharsetANSI weight:0];
        [richtext_style setFont:rcstyle_font_2];
        int rc_count = [freetext getRichTextCount];
        [freetext insertRichText:(rc_count-1) content:@"2_strikethrough " style:richtext_style];
        // Appearance should be reset.
        [freetext resetAppearanceStream];
        NSLog(@"Add a typewriter freetext annotation with richtext.");
        
    }
    {
        // Add freetext annotation with richtext, as call-out.
        FSRectF* annot_rect = [[FSRectF alloc] initWithLeft1:300 bottom1:50 right1:400 top1:100];
        FSFreeText* freetext = [[FSFreeText alloc] initWithAnnot:[page addAnnot:FSAnnotFreeText rect:annot_rect]];
        //This flag is used for printing annotations.
        [freetext setFlags:4];
        // Set default appearance
        unsigned int da_flags = FSDefaultAppearanceFlagFont | FSDefaultAppearanceFlagFontSize | FSDefaultAppearanceFlagTextColor;
        FSFont* da_font = [[FSFont alloc] initWithFont_id:FSFontStdIDHelveticaB];
        FSDefaultAppearance* default_ap = [[FSDefaultAppearance alloc] initWithFlags:da_flags font:da_font text_size:12.0 text_color:0x000000];
        // Set default appearance for form.
        [freetext setDefaultAppearance:default_ap];
        [freetext setIntent:@"FreeTextCallout"];
        FSPointFArray* callout_points = [FSPointFArray new];
        FSPointF* point = [FSPointF new];
        [point set:250 y:60];
        [callout_points add:point];
        [point set:280 y:80];
        [callout_points add:point];
        [point set:300 y:80];
        [callout_points add:point];
        [freetext setCalloutLinePoints:callout_points];
        [freetext setCalloutLineEndingStyle:FSMarkupEndingStyleOpenArrow];
        
        [freetext setContent:@"A callout annotation."];
        [freetext setSubject:@"FreeTextCallout"];
        [freetext setTitle:@"Foxit SDK"];
        FSDateTime* local_time = getLocalDateTime();
        [freetext setCreationDateTime:local_time];
        [freetext setModifiedDateTime:local_time];
        [freetext setUniqueID:randomUID()];
        
        FSRichTextStyle* richtext_style = [[FSRichTextStyle alloc] init];
        FSFont* rcstyle_font_1 = [[FSFont alloc] initWithName:@"Times New Roman" styles:0 charset:FSFontCharsetANSI weight:0];
        [richtext_style setFont:rcstyle_font_1];
        [richtext_style setText_color:0xFF0000];
        [richtext_style setText_size:10];
        [freetext addRichText:@"Callout annotation " style:richtext_style];
        
        [richtext_style setText_color:0x00FF00];
        [richtext_style setIs_underline:YES];
        [freetext addRichText:@"1-underline " style:richtext_style];
        
        [richtext_style setIs_underline:NO];
        [richtext_style setText_color:0x0000FF];
        [richtext_style setIs_strikethrough:YES];
        FSFont* rcstyle_font_2 = [[FSFont alloc] initWithName:@"Calibri" styles:0 charset:FSFontCharsetANSI weight:0];
        [richtext_style setFont:rcstyle_font_2];
        int rc_count = [freetext getRichTextCount];
        [freetext insertRichText:(rc_count-1) content:@"2_strikethrough " style:richtext_style];
        // Appearance should be reset.
        [freetext resetAppearanceStream];
        NSLog(@"Add a callout freetext annotation with richtext.");
    }
    {
        // Add freetext annotation with richtext, as text box.
        FSRectF* annot_rect = [[FSRectF alloc] initWithLeft1:450 bottom1:50 right1:550 top1:100];
        FSFreeText* freetext = [[FSFreeText alloc] initWithAnnot:[page addAnnot:FSAnnotFreeText rect:annot_rect]];
        //This flag is used for printing annotations.
        [freetext setFlags:4];
        // Set default appearance
        unsigned int da_flags = FSDefaultAppearanceFlagFont | FSDefaultAppearanceFlagFontSize | FSDefaultAppearanceFlagTextColor;
        FSFont* da_font = [[FSFont alloc] initWithFont_id:FSFontStdIDHelveticaI];
        FSDefaultAppearance* default_ap = [[FSDefaultAppearance alloc] initWithFlags:da_flags font:da_font text_size:12.0 text_color:0x000000];
        // Set default appearance for form.
        [freetext setDefaultAppearance:default_ap];
        [freetext setContent:@"A text box annotation."];
        [freetext setSubject:@"Textbox"];
        [freetext setTitle:@"Foxit SDK"];
        FSDateTime* local_time = getLocalDateTime();
        [freetext setCreationDateTime:local_time];
        [freetext setModifiedDateTime:local_time];
        [freetext setUniqueID:randomUID()];
        
        FSRichTextStyle* richtext_style = [[FSRichTextStyle alloc] init];
        FSFont* rcstyle_font_1 = [[FSFont alloc] initWithName:@"Times New Roman" styles:0 charset:FSFontCharsetANSI weight:0];
        [richtext_style setFont:rcstyle_font_1];
        [richtext_style setText_color:0xFF0000];
        [richtext_style setText_size:10];
        [freetext addRichText:@"Textbox annotation " style:richtext_style];
        
        [richtext_style setText_color:0x00FF00];
        [richtext_style setIs_underline:YES];
        [freetext addRichText:@"1-underline " style:richtext_style];
        
        [richtext_style setIs_underline:NO];
        [richtext_style setText_color:0x0000FF];
        [richtext_style setIs_strikethrough:YES];
        FSFont* rcstyle_font_2 = [[FSFont alloc] initWithName:@"Calibri" styles:0 charset:FSFontCharsetANSI weight:0];
        [richtext_style setFont:rcstyle_font_2];
        int rc_count = [freetext getRichTextCount];
        [freetext insertRichText:(rc_count-1) content:@"2_strikethrough " style:richtext_style];
        // Appearance should be reset.
        [freetext resetAppearanceStream];
        NSLog(@"Add a text box freetext annotation with richtext.");
    }
    {
        //Add a screen annotation.
        FSRectF* annot_rect = [[FSRectF alloc] initWithLeft1:300 bottom1:150 right1:400 top1:200];
        FSScreen* screen = [[FSScreen alloc] initWithAnnot:[page addAnnot:FSAnnotScreen rect:annot_rect]];
        //This flag is used for printing annotations.
        [screen setFlags:4];
        NSString *image_path = [input_path stringByAppendingString:@"FoxitLogo.jpg"];
        FSImage* image = [[FSImage alloc] initWithPath:image_path];
        [screen setTitle:@"Foxit SDK"];
        [screen setBorderColor:0x0000FF];
        FSFloatArray* floatArray = [FSFloatArray new];
        FSBorderInfo* borderinfo = [[FSBorderInfo alloc] initWithWidth:2 style:FSBorderInfoSolid intensity:0 dash_phase:0 dashes:floatArray];
        [screen setBorderInfo:borderinfo];
        [screen setImage:image frame_index:0 compress:1];

        //Prepare rendition action.
        FSPDFDoc* doc = [page getDocument];
        FSRenditionAction* rendition_action = [[FSRenditionAction alloc] initWithAction:[FSAction create:doc action_type:FSActionTypeRendition]];
        [rendition_action setOperationType:FSRenditionActionOpTypeAssociate];       
        [rendition_action setScreenAnnot:screen];

        //Prepare rendition.
        FSRendition* rendition = [[FSRendition alloc] initWithPdf_doc:doc rendition_dict:nil];
        [rendition setRenditionName:@"screen for rendition"];
        [rendition setMediaClipName:@"ytb210-Mopa.mp4"];
        [rendition setPermission:FSRenditionMediaPermTempAccess];
        FSFileSpec* video_filespec = [[FSFileSpec alloc] initWithDocument:doc];
        [video_filespec setFileName:@"ytb210-Mopa.mp4"];

        NSString *video_file_path = [input_path stringByAppendingString:@"ytb210-Mopa.mp4"];
        [video_filespec embed:video_file_path];
        [rendition setMediaClipFile:video_filespec];
        [rendition setMediaClipContentType:@"video/mp4"];

        [rendition_action insertRendition:rendition index:-1];

        [screen setAction:rendition_action];
        [screen resetAppearanceStream];
        NSLog(@"Add a screen annotation.");
    }
}

void AddAnnotsWithLowLevelAPI(FSPDFPage* page)
{
    {
        // Add line annotation
        FSPDFDictionary* annot_dict = [FSPDFDictionary create];
        [annot_dict setAtName:@"Type" value:@"Annot"];
        [annot_dict setAtName:@"Subtype" value:@"Line"];
        [annot_dict setAtName:@"IT" value:@"LineArrow"];
        [annot_dict setAtInteger:@"F" value:4];
        [annot_dict setAtString:@"Contents" value:@"A line arrow annotation."];
        [annot_dict setAtString:@"T" value:@"Foxit SDK"];
        [annot_dict setAtString:@"Subj" value:@"Arrow"];
        [annot_dict setAtString:@"NM" value:randomUID()];
        [annot_dict setAtDateTime:@"CreationDate" value:getLocalDateTime()];
        [annot_dict setAtDateTime:@"M" value:getLocalDateTime()];
        FSRectF* annot_rect = [[FSRectF alloc] initWithLeft1:0 bottom1:650 right1:100 top1:750];
        [annot_dict setAtRect:@"Rect" value:annot_rect];
        FSPDFArray* coords_array = [FSPDFArray create];
        [coords_array addFloat:20];
        [coords_array addFloat:670];
        [coords_array addFloat:80];
        [coords_array addFloat:730];
        [annot_dict setAt:@"L" pdf_object:coords_array];
        FSPDFArray* line_style = [FSPDFArray create];
        [line_style addName:@"None"];
        [line_style addName:@"OpenArrow"];
        [annot_dict setAt:@"LE"  pdf_object:line_style];
        FSPDFDictionary* border_dict = [FSPDFDictionary create];
        [border_dict setAtFloat:@"W" value:2.0f];
        [border_dict setAtName:@"S" value:@"S"];
        [border_dict setAtName:@"Type" value:@"Border"];
        [annot_dict setAt:@"BS" pdf_object:border_dict];
        FSPDFArray* color_array = [FSPDFArray create];
        [color_array addFloat:1];
        [color_array addFloat:1];
        [color_array addFloat:0];
        [annot_dict setAt:@"C" pdf_object:color_array];
        FSAnnot* annot = [page addAnnotWithDictionary:annot_dict];
        [annot resetAppearanceStream];
        NSLog(@"Add a line annotation by lower level API.");
    }

    {
        // Add line annotation with caption
        FSPDFDictionary* annot_dict = [FSPDFDictionary create];
        [annot_dict setAtName:@"Type" value:@"Annot"];
        [annot_dict setAtName:@"Subtype" value:@"Line"];
        [annot_dict setAtName:@"IT" value:@"LineArrow"];
        [annot_dict setAtInteger:@"F" value:4];
        [annot_dict setAtString:@"Contents" value:@"A common line."];
        [annot_dict setAtString:@"T" value:@"Foxit SDK"];
        [annot_dict setAtString:@"Subj" value:@"Line"];
        [annot_dict setAtString:@"NM" value:randomUID()];
        [annot_dict setAtDateTime:@"CreationDate" value:getLocalDateTime()];
        [annot_dict setAtDateTime:@"M" value:getLocalDateTime()];
        FSRectF* annot_rect = [[FSRectF alloc] initWithLeft1:0 bottom1:650 right1:100 top1:750];
        [annot_dict setAtRect:@"Rect" value:annot_rect];
        [annot_dict setAtBoolean:@"Cap" value:true];
        FSPDFArray* caption_offset = [FSPDFArray create];
        [caption_offset addFloat:0];
        [caption_offset addFloat:5];
        [annot_dict setAt:@"CO" pdf_object:caption_offset];
        FSPDFArray* coords_array = [FSPDFArray create];
        [coords_array addFloat:40];
        [coords_array addFloat:670];
        [coords_array addFloat:100];
        [coords_array addFloat:730];
        [annot_dict setAt:@"L" pdf_object:coords_array];
        FSPDFArray* line_style = [FSPDFArray create];
        [line_style addName:@"Square"];
        [line_style addName:@"OpenArrow"];
        [annot_dict setAt:@"LE"  pdf_object:line_style];
        FSPDFDictionary* border_dict = [FSPDFDictionary create];
        [border_dict setAtFloat:@"W" value:2.0f];
        [border_dict setAtName:@"S" value:@"S"];
        [border_dict setAtName:@"Type" value:@"Border"];
        [annot_dict setAt:@"BS" pdf_object:border_dict];
        FSPDFArray* color_array = [FSPDFArray create];
        [color_array addFloat:0];
        [color_array addFloat:1];
        [color_array addFloat:0];
        [annot_dict setAt:@"C" pdf_object:color_array];
        FSAnnot* annot = [page addAnnotWithDictionary:annot_dict];
        [annot resetAppearanceStream];
        NSLog(@"Add a line annotation with caption by lower level API.");
  }

  {
      // Add circle annotation
      FSPDFDictionary* annot_dict = [FSPDFDictionary create];
      [annot_dict setAtName:@"Type" value:@"Annot"];
      [annot_dict setAtName:@"Subtype" value:@"Circle"];
      [annot_dict setAtInteger:@"F" value:4];
      [annot_dict setAtString:@"T" value:@"Foxit SDK"];
      [annot_dict setAtString:@"Subj" value:@"Circle"];
      [annot_dict setAtString:@"NM" value:randomUID()];
      [annot_dict setAtDateTime:@"CreationDate" value:getLocalDateTime()];
      [annot_dict setAtDateTime:@"M" value:getLocalDateTime()];
      FSRectF* annot_rect = [[FSRectF alloc] initWithLeft1:120 bottom1:650 right1:180 top1:750];
      [annot_dict setAtRect:@"Rect" value:annot_rect];
      FSPDFDictionary* border_dict = [FSPDFDictionary create];
      [border_dict setAtFloat:@"W" value:2.0f];
      [border_dict setAtName:@"S" value:@"S"];
      [border_dict setAtName:@"Type" value:@"Border"];
      [annot_dict setAt:@"BS" pdf_object:border_dict];
      FSPDFArray* color_array = [FSPDFArray create];
      [color_array addFloat:0];
      [color_array addFloat:1];
      [color_array addFloat:0];
      [annot_dict setAt:@"C" pdf_object:color_array];
      FSAnnot* annot = [page addAnnotWithDictionary:annot_dict];
      [annot resetAppearanceStream];
      NSLog(@"Add a circle annotation by lower level API.");
  }

  {
      // Add square annotation
      FSPDFDictionary* annot_dict = [FSPDFDictionary create];
      [annot_dict setAtName:@"Type" value:@"Annot"];
      [annot_dict setAtName:@"Subtype" value:@"Square"];
      [annot_dict setAtInteger:@"F" value:4];
      [annot_dict setAtString:@"T" value:@"Foxit SDK"];
      [annot_dict setAtString:@"Subj" value:@"Square"];
      [annot_dict setAtString:@"NM" value:randomUID()];
      [annot_dict setAtDateTime:@"CreationDate" value:getLocalDateTime()];
      [annot_dict setAtDateTime:@"M" value:getLocalDateTime()];
      FSRectF* annot_rect = [[FSRectF alloc] initWithLeft1:200 bottom1:650 right1:300 top1:750];
      [annot_dict setAtRect:@"Rect" value:annot_rect];
      FSPDFDictionary* border_dict = [FSPDFDictionary create];
      [border_dict setAtFloat:@"W" value:2.0f];
      [border_dict setAtName:@"S" value:@"S"];
      [border_dict setAtName:@"Type" value:@"Border"];
      [annot_dict setAt:@"BS" pdf_object:border_dict];
      FSPDFArray* color_array = [FSPDFArray create];
      [color_array addFloat:0];
      [color_array addFloat:1];
      [color_array addFloat:0];
      [annot_dict setAt:@"C" pdf_object:color_array];
      FSPDFArray* interior_color_array = [FSPDFArray create];
      [interior_color_array addFloat:1];
      [interior_color_array addFloat:1];
      [interior_color_array addFloat:0];
      [annot_dict setAt:@"IC" pdf_object:interior_color_array];
      FSAnnot* annot = [page addAnnotWithDictionary:annot_dict];
      [annot resetAppearanceStream];
      NSLog(@"Add a square annotation by lower level API.");
  }
}

bool SaveSoundToFile(FSSound* sound, NSString* file_path)
{
    @try {
        if ([sound isEmpty]) {
            return NO;
        }
        FSPDFStream *soundStream = [sound getSoundStream];
        NSMutableData *data = [NSMutableData dataWithData:[soundStream getData:NO]];
        NSFileManager *defaultManager = [NSFileManager defaultManager];
        
        if (![defaultManager fileExistsAtPath:[file_path stringByDeletingLastPathComponent]]) {
            [defaultManager createDirectoryAtPath:[file_path stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:nil];
        }
        
        NSMutableData *randomAccessFile = [NSMutableData data];
        uint64_t streamSize = [soundStream getDataSize:NO];
        
        short bit = (short) sound.getBits;

        uint64_t riffSize = streamSize + 36;
        
        NSUInteger lInt = 4;
        NSUInteger sInt = 2;
        
        [randomAccessFile appendData:[@"RIFF" dataUsingEncoding:NSUTF8StringEncoding]];
        [randomAccessFile appendBytes:&riffSize length:lInt];
        [randomAccessFile appendData:[@"WAVEfmt " dataUsingEncoding:NSUTF8StringEncoding]];
        
        NSUInteger chunkSize = 16;
        [randomAccessFile appendBytes:&chunkSize length:lInt];
        
        short format = 1;
        [randomAccessFile appendBytes:&format length:sInt];
        
        short channelCount = sound.getChannelCount;
        [randomAccessFile appendBytes:&channelCount length:sInt];
        
        int64_t rate = (int64_t)sound.getSamplingRate;
        [randomAccessFile appendBytes:&rate length:lInt];
        
        int64_t bytePerSec = rate * channelCount * bit / 8;
        [randomAccessFile appendBytes:&bytePerSec length:lInt];
        
        short blockAlign = (short) (bit * channelCount / 8);
        [randomAccessFile appendBytes:&blockAlign length:sInt];
        [randomAccessFile appendBytes:&bit length:sInt];
        [randomAccessFile appendData:[@"data" dataUsingEncoding:NSUTF8StringEncoding]];
        
        BOOL ret = NO;
        NSUInteger encodingFormat = sound.getSampleEncodingFormat;
        switch (encodingFormat) {
            case FSSoundSampleEncodingFormatALaw:
                break;
            case FSSoundSampleEncodingFormatMuLaw:
                break;
            case FSSoundSampleEncodingFormatSigned:
            {
                NSMutableData *buffer = [NSMutableData data];
                int j = 0, k = 0;
                for (int i = 0; i < streamSize; i += 2) {
                    NSData *low = [data subdataWithRange:NSMakeRange(j++, 1)];
                    NSData *high = [data subdataWithRange:NSMakeRange(j++, 1)];
                    [buffer replaceBytesInRange:NSMakeRange(k++, 1) withBytes:high.bytes];
                    [buffer replaceBytesInRange:NSMakeRange(k++, 1) withBytes:low.bytes];
                }
                [randomAccessFile appendData:buffer];
                ret = YES;
            }
                break;
            case FSSoundSampleEncodingFormatRaw:
            default:
            {
                [randomAccessFile appendData:data];
                ret = YES;
            }
                break;
        }
       
        return [randomAccessFile writeToFile:file_path atomically:YES];
    } @catch (NSException *exception) {
        return NO;
    }
}

FSAnnot* GetAnnotWithType(FSPDFPage* pdf_page, FSAnnotType annot_type, const int annot_index_with_type, int& annot_index_with_all)
{
    if ([pdf_page isEmpty] || annot_type<(FSAnnotType)-1) return NULL;

    FSAnnot* ret_annot;
    int annot_count = [pdf_page getAnnotCount];
    int spec_annot_index = -1;
    for (int i = 0; i < annot_count; i++)
    {
        FSAnnot* annot_i = [pdf_page getAnnot:i];
        int cmp_index = -1;

        if ((FSAnnotType)-1 == annot_type)
        {
            cmp_index = i;
        }
        else if ([annot_i getType] == annot_type)
        {
            spec_annot_index ++;
            cmp_index = spec_annot_index;
        }
        if (cmp_index == annot_index_with_type)
        {
            annot_index_with_all = i;
            ret_annot = annot_i;
            break;
        }
    }
    return ret_annot;
}

FSSound* GetSoundAnnot(NSString* input_pdf_path ,int page_index)
{
    FSPDFDoc *doc = [[FSPDFDoc alloc] initWithPath:input_pdf_path];
    [doc load:nil];
    FSPDFPage* pdf_page = [doc getPage:0];
    if ([pdf_page isEmpty])
    {
        return NULL;
    }

    int annot_index_with_type = 0;
    int annot_index_with_all = 0;
    FSAnnot* annot = GetAnnotWithType(pdf_page, FSAnnotSound, annot_index_with_type, annot_index_with_all);
    if ([annot isEmpty])
    {
        return NULL;
    }
    if ([annot getType] != FSAnnotSound)
    {
        return NULL;
    }
    FSSound* sound = [[FSSound alloc] initWithAnnot:annot];
    return sound;
}

int main(int argc, const char * argv[]) {
	bool is_run_success = false;
    bool is_run_success_lower_api = false;
	@autoreleasepool {
        NSString *output_directory = [output_path stringByAppendingString:@"annotation/"];
        NSFileManager *fileManager = [NSFileManager defaultManager];
		BOOL isDir = NO;
		if ([fileManager fileExistsAtPath:output_directory isDirectory:&isDir]) {
			if (!isDir) {
				NSError *error = nil;
				if (![fileManager removeItemAtPath:output_directory error:&error] || error) {
					return -1;
				}
				if (![fileManager createDirectoryAtPath:output_directory withIntermediateDirectories:YES attributes:nil error:&error] || error) {
					return -1;
				}
			}
		} else {
			NSError *error = nil;
			if (![fileManager createDirectoryAtPath:output_directory withIntermediateDirectories:YES attributes:nil error:&error] || error) {
				return -1;
			}
		}
    
		// Initialize library
		FSErrorCode errorCode = [FSLibrary initialize:sn key:key];
		if (errorCode != FSErrSuccess) {
			NSLog(@"Library Initialize Error: %ld", errorCode);
			return -1;
		}
		
		@try {
            NSString* input_pdf_name = @"annotation_input.pdf";
            NSString* input_pdf_path = [input_path stringByAppendingPathComponent:input_pdf_name];
            // Load a document
            FSPDFDoc* doc = [[FSPDFDoc alloc] initWithPath:input_pdf_path];
            FSErrorCode errorCode = [doc load:nil];
            if (errorCode != FSErrSuccess) {
                NSLog(@"The Doc [%@] Error: %ld", input_pdf_path, errorCode);
                return -1;
            }
            // Get first page with index 0
            FSPDFPage* page = [doc getPage:0];
            addAnnotations(page);
            // Save PDF file
            NSString* save_pdf_path = [output_directory stringByAppendingPathComponent:@"annotation.pdf"];
            [doc saveAs:save_pdf_path save_flags:FSPDFDocSaveFlagNoOriginal];
            
            NSLog(@"Annotation test.");
            is_run_success = true;
		}
		@catch (NSException *e) {
			NSLog(@"Unknown Exception, %@", e);
		}
		
		@try {
            NSString* input_pdf_name = @"annotation_input.pdf";
            NSString* input_pdf_path = [input_path stringByAppendingPathComponent:input_pdf_name];
            // Load a document
            FSPDFDoc* doc = [[FSPDFDoc alloc] initWithPath:input_pdf_path];
            FSErrorCode errorCode = [doc load:nil];
            if (errorCode != FSErrSuccess) {
                NSLog(@"The Doc [%@] Error: %ld", input_pdf_path, errorCode);
                return -1;
            }
            // Get first page with index 0
            FSPDFPage* page = [doc getPage:0];
            AddAnnotsWithLowLevelAPI(page);
            // Save PDF file
            NSString* save_pdf_path = [output_directory stringByAppendingPathComponent:@"annotation_lower_level_API.pdf"];
            [doc saveAs:save_pdf_path save_flags:FSPDFDocSaveFlagNoOriginal];
            
            NSLog(@"Annotation lower level API test.");
            is_run_success_lower_api = true;
		}
		@catch (NSException *e) {
			NSLog(@"Unknown Exception, %@", e);
		}
        
        //save sound to file:
        @try {
            NSString* output_sound_file = [output_directory stringByAppendingPathComponent:@"sound.wav"];
            NSString* input_sound_pdf_file = [input_path stringByAppendingPathComponent:@"sound.pdf"];
            FSSound* sound = GetSoundAnnot(input_sound_pdf_file, 0);
            if (SaveSoundToFile(sound, output_sound_file))
			{
				NSLog(@"Save sound annotation to file, saved file path:%@",output_sound_file);
			}
        }
        @catch (NSException *e) {
            NSLog(@"Unknown Exception, %@", e);
        }       
	}
    [FSLibrary destroy];
	return (is_run_success && is_run_success_lower_api)? 0 : 1;
}
