HPDF_FontDef
HPDF_Type1FontDef_New  (HPDF_MMgr  mmgr)
{
    HPDF_FontDef fontdef;
    HPDF_Type1FontDefAttr fontdef_attr;

    HPDF_PTRACE (" HPDF_Type1FontDef_New\n");

    if (!mmgr)
        return NULL;

    fontdef = HPDF_GetMem (mmgr, sizeof(HPDF_FontDef_Rec));
    if (!fontdef)
        return NULL;

    HPDF_MemSet (fontdef, 0, sizeof (HPDF_FontDef_Rec));
    fontdef->sig_bytes = HPDF_FONTDEF_SIG_BYTES;
    fontdef->mmgr = mmgr;
    fontdef->error = mmgr->error;
    fontdef->type = HPDF_FONTDEF_TYPE_TYPE1;
    fontdef->free_fn = FreeFunc;

    fontdef_attr = HPDF_GetMem (mmgr, sizeof(HPDF_Type1FontDefAttr_Rec));
    if (!fontdef_attr) {
        HPDF_FreeMem (fontdef->mmgr, fontdef);
        return NULL;
    }

    fontdef->attr = fontdef_attr;
    HPDF_MemSet ((HPDF_BYTE *)fontdef_attr, 0, sizeof(HPDF_Type1FontDefAttr_Rec));
    fontdef->flags = HPDF_FONT_STD_CHARSET;

    return fontdef;
}
Example #2
0
static HPDF_STATUS
ReadTransparentPaletteData  (HPDF_Dict    image,
                             png_structp  png_ptr,
                             png_infop    info_ptr,
                             png_bytep    smask_data,
                             png_bytep    trans,
                             int          num_trans)
{
	HPDF_STATUS ret = HPDF_OK;
	HPDF_UINT i, j;
	png_bytep *row_ptr;
	png_uint_32 height = png_get_image_height(png_ptr, info_ptr);
	png_uint_32 width = png_get_image_width(png_ptr, info_ptr);

	row_ptr = HPDF_GetMem (image->mmgr, height * sizeof(png_bytep));
	if (!row_ptr) {
		return HPDF_FAILD_TO_ALLOC_MEM;
	} else {
		png_uint_32 len = png_get_rowbytes(png_ptr, info_ptr);

		for (i = 0; i < (HPDF_UINT)height; i++) {
			row_ptr[i] = HPDF_GetMem(image->mmgr, len);
			if (!row_ptr[i]) {
				for (; i > 0; i--) {
					HPDF_FreeMem (image->mmgr, row_ptr[i]);
				}
				HPDF_FreeMem (image->mmgr, row_ptr);
				return HPDF_FAILD_TO_ALLOC_MEM;
			}
		}
	}

	png_read_image(png_ptr, row_ptr);
	if (image->error->error_no != HPDF_OK) {
		ret = HPDF_INVALID_PNG_IMAGE;
		goto Error;
	}

	for (j = 0; j < height; j++) {
		for (i = 0; i < width; i++) {
			smask_data[width * j + i] = (row_ptr[j][i] < num_trans) ? trans[row_ptr[j][i]] : 0xFF;
		}

		if (HPDF_Stream_Write (image->stream, row_ptr[j], width) != HPDF_OK) {
			ret = HPDF_FILE_IO_ERROR;
			goto Error;
		}
	}

Error:
	for (i = 0; i < (HPDF_UINT)height; i++) {
		HPDF_FreeMem (image->mmgr, row_ptr[i]);
	}

	HPDF_FreeMem (image->mmgr, row_ptr);
	return ret;
}
Example #3
0
HPDF_Xref
HPDF_Xref_New  (HPDF_MMgr     mmgr,
                HPDF_UINT32   offset)
{
    HPDF_Xref xref;
    HPDF_XrefEntry new_entry;

    HPDF_PTRACE((" HPDF_Xref_New\n"));

    xref = (HPDF_Xref)HPDF_GetMem (mmgr, sizeof(HPDF_Xref_Rec));
    if (!xref)
        return NULL;

    HPDF_MemSet (xref, 0, sizeof(HPDF_Xref_Rec));
    xref->mmgr = mmgr;
    xref->error = mmgr->error;
    xref->start_offset = offset;

    xref->entries = HPDF_List_New (mmgr, HPDF_DEFALUT_XREF_ENTRY_NUM);
    if (!xref->entries)
        goto Fail;

    xref->addr = 0;

    if (xref->start_offset == 0) {
        new_entry = (HPDF_XrefEntry)HPDF_GetMem (mmgr,
                sizeof(HPDF_XrefEntry_Rec));
        if (!new_entry)
            goto Fail;

        if (HPDF_List_Add (xref->entries, new_entry) != HPDF_OK) {
            HPDF_FreeMem (mmgr, new_entry);
            goto Fail;
        }

        /* add first entry which is free entry and whose generation
         * number is 0
         */
        new_entry->entry_typ = HPDF_FREE_ENTRY;
        new_entry->byte_offset = 0;
        new_entry->gen_no = HPDF_MAX_GENERATION_NUM;
        new_entry->obj = NULL;
    }

    xref->trailer = HPDF_Dict_New (mmgr);
    if (!xref->trailer)
        goto Fail;

    return xref;

Fail:
    HPDF_PTRACE((" HPDF_Xref_New failed\n"));
    HPDF_Xref_Free (xref);
    return NULL;
}
HPDF_FontDef
HPDF_CIDFontDef_New  (HPDF_MMgr               mmgr,
                      char              *name,
                      HPDF_FontDef_InitFunc   init_fn)
{
    HPDF_FontDef fontdef;
    HPDF_CIDFontDefAttr fontdef_attr;

    HPDF_PTRACE (" HPDF_CIDFontDef_New\n");

    if (!mmgr)
        return NULL;

    fontdef = HPDF_GetMem (mmgr, sizeof(HPDF_FontDef_Rec));
    if (!fontdef)
        return NULL;

    HPDF_MemSet (fontdef, 0, sizeof(HPDF_FontDef_Rec));
    fontdef->sig_bytes = HPDF_FONTDEF_SIG_BYTES;
    HPDF_StrCpy (fontdef->base_font, name, fontdef->base_font +
                    HPDF_LIMIT_MAX_NAME_LEN);
    fontdef->mmgr = mmgr;
    fontdef->error = mmgr->error;
    fontdef->type = HPDF_FONTDEF_TYPE_UNINITIALIZED;
    fontdef->free_fn = HPDF_CIDFontDef_FreeFunc;
    fontdef->init_fn = init_fn;
    fontdef->valid = HPDF_FALSE;
    fontdef_attr = HPDF_GetMem (mmgr, sizeof(HPDF_CIDFontDefAttr_Rec));
    if (!fontdef_attr) {
        HPDF_FreeMem (fontdef->mmgr, fontdef);
        return NULL;
    }

    fontdef->attr = fontdef_attr;
    HPDF_MemSet ((HPDF_BYTE *)fontdef_attr, 0,
                sizeof(HPDF_CIDFontDefAttr_Rec));

    fontdef_attr->widths = HPDF_List_New (mmgr, HPDF_DEF_CHAR_WIDTHS_NUM);
    if (!fontdef_attr->widths) {
        HPDF_FreeMem (fontdef->mmgr, fontdef);
        HPDF_FreeMem (fontdef->mmgr, fontdef_attr);
        return NULL;
    }

    fontdef->missing_width = 500;
    fontdef_attr->DW = 1000;
    fontdef_attr->DW2[0] = 880;
    fontdef_attr->DW2[1] = -1000;

    return fontdef;
}
Example #5
0
static HPDF_STATUS
ReadPngData  (HPDF_Dict    image,
              png_structp  png_ptr,
              png_infop    info_ptr)
{
    png_uint_32 len = png_get_rowbytes(png_ptr, info_ptr);
    png_uint_32 height = png_get_image_height(png_ptr, info_ptr);
    png_bytep buf_ptr = HPDF_GetMem (image->mmgr, len);

    if (buf_ptr) {
        HPDF_UINT i;

        for (i = 0; i < (HPDF_UINT)height; i++) {
            png_read_rows(png_ptr, (png_byte**)&buf_ptr, NULL, 1);
            if (image->error->error_no != HPDF_OK)
                break;

            if (HPDF_Stream_Write (image->stream, buf_ptr, len) != HPDF_OK)
                break;
        }

        HPDF_FreeMem (image->mmgr, buf_ptr);
    }

    return image->error->error_no;
}
Example #6
0
static HPDF_STATUS
Resize  (HPDF_List   list,
         HPDF_UINT   count)
{
    void **new_obj;

    HPDF_PTRACE((" HPDF_List_Resize\n"));

    if (list->count >= count) {
        if (list->count == count)
            return HPDF_OK;
        else
            return HPDF_INVALID_PARAMETER;
    }

    new_obj = (void **)HPDF_GetMem (list->mmgr, count * sizeof(void *));

    if (!new_obj)
        return HPDF_Error_GetCode (list->error);

    if (list->obj)
        HPDF_MemCpy ((HPDF_BYTE *)new_obj, (HPDF_BYTE *)list->obj,
                list->block_siz * sizeof(void *));

    list->block_siz = count;
    if (list->obj)
        HPDF_FreeMem (list->mmgr, list->obj);
    list->obj = new_obj;

    return HPDF_OK;
}
Example #7
0
HPDF_EncryptDict
HPDF_EncryptDict_New  (HPDF_MMgr  mmgr,
                       HPDF_Xref  xref)
{
    HPDF_Encrypt attr;
    HPDF_EncryptDict dict;

    HPDF_PTRACE((" HPDF_EncryptDict_New\n"));

    dict = HPDF_Dict_New (mmgr);
    if (!dict)
        return NULL;

    dict->header.obj_class |= HPDF_OSUBCLASS_ENCRYPT;
    dict->free_fn = HPDF_EncryptDict_OnFree;

    attr = HPDF_GetMem (dict->mmgr, sizeof(HPDF_Encrypt_Rec));
    if (!attr) {
        HPDF_Dict_Free (dict);
        return NULL;
    }

    dict->attr = attr;
    HPDF_Encrypt_Init (attr);

    if (HPDF_Xref_Add (xref, dict) != HPDF_OK)
        return NULL;

    return dict;
}
Example #8
0
HPDF_String
HPDF_String_New  (HPDF_MMgr        mmgr,
                  const char  *value,
                  HPDF_Encoder     encoder)
{
    HPDF_String obj;

    HPDF_PTRACE((" HPDF_String_New\n"));

    obj = (HPDF_String)HPDF_GetMem (mmgr, sizeof(HPDF_String_Rec));
    if (obj) {
        HPDF_MemSet (&obj->header, 0, sizeof(HPDF_Obj_Header));
        obj->header.obj_class = HPDF_OCLASS_STRING;

        obj->mmgr = mmgr;
        obj->error = mmgr->error;
        obj->encoder = encoder;
        obj->value = NULL;
        obj->len = 0;

        if (HPDF_String_SetValue (obj, value) != HPDF_OK) {
            HPDF_FreeMem (obj->mmgr, obj);
            return NULL;
        }
    }

    return obj;
}
Example #9
0
HPDF_STATUS
HPDF_String_SetValue  (HPDF_String      obj,
                       const char  *value)
{
    HPDF_UINT len;
    HPDF_STATUS ret = HPDF_OK;

    HPDF_PTRACE((" HPDF_String_SetValue\n"));

    if (obj->value) {
        HPDF_FreeMem (obj->mmgr, obj->value);
        obj->len = 0;
    }

    len = HPDF_StrLen(value, HPDF_LIMIT_MAX_STRING_LEN + 1);

    if (len > HPDF_LIMIT_MAX_STRING_LEN)
        return HPDF_SetError (obj->error, HPDF_STRING_OUT_OF_RANGE, 0);

    obj->value = HPDF_GetMem (obj->mmgr, len + 1);
    if (!obj->value)
        return HPDF_Error_GetCode (obj->error);

    HPDF_StrCpy ((char *)obj->value, value, (char *)obj->value + len);
    obj->len = len;

    return ret;
}
Example #10
0
HPDF_Binary
HPDF_Binary_New  (HPDF_MMgr  mmgr,
                  HPDF_BYTE  *value,
                  HPDF_UINT  len)
{
    HPDF_Binary obj;

    obj  = HPDF_GetMem (mmgr, sizeof(HPDF_Binary_Rec));

    if (obj) {
        HPDF_MemSet(&obj->header, 0, sizeof(HPDF_Obj_Header));
        obj->header.obj_class = HPDF_OCLASS_BINARY;

        obj->mmgr = mmgr;
        obj->error = mmgr->error;
        obj->value = NULL;
        obj->len = 0;
        if (HPDF_Binary_SetValue (obj, value, len) != HPDF_OK) {
            HPDF_FreeMem (mmgr, obj);
            return NULL;
        }
    }

    return obj;
}
HPDF_STATUS
HPDF_CIDFontDef_AddWidth  (HPDF_FontDef            fontdef,
                           const HPDF_CID_Width   *widths)
{
    HPDF_CIDFontDefAttr attr = (HPDF_CIDFontDefAttr)fontdef->attr;

    HPDF_PTRACE (" HPDF_CIDFontDef_AddWidth\n");

    while (widths->cid != 0xFFFF) {
        HPDF_CID_Width *w = HPDF_GetMem (fontdef->mmgr,
                sizeof (HPDF_CID_Width));
        HPDF_STATUS ret;

        if (!w)
            return fontdef->error->error_no;

        w->cid = widths->cid;
        w->width = widths->width;

        if ((ret = HPDF_List_Add (attr->widths, w)) != HPDF_OK) {
            HPDF_FreeMem (fontdef->mmgr, w);

            return ret;
        }

        widths++;
    }

    return HPDF_OK;
}
Example #12
0
HPDF_STATUS
HPDF_Xref_Add  (HPDF_Xref  xref,
                void       *obj)
{
    HPDF_XrefEntry entry;
    HPDF_Obj_Header *header;

    HPDF_PTRACE((" HPDF_Xref_Add\n"));

    if (!obj) {
        if (HPDF_Error_GetCode (xref->error) == HPDF_OK)
            return HPDF_SetError (xref->error, HPDF_INVALID_OBJECT, 0);
        else
            return HPDF_INVALID_OBJECT;
    }

    header = (HPDF_Obj_Header *)obj;

    if (header->obj_id & HPDF_OTYPE_DIRECT ||
            header->obj_id & HPDF_OTYPE_INDIRECT)
        return HPDF_SetError(xref->error, HPDF_INVALID_OBJECT, 0);

    if (xref->entries->count >= HPDF_LIMIT_MAX_XREF_ELEMENT) {
        HPDF_SetError(xref->error, HPDF_XREF_COUNT_ERR, 0);
        goto Fail;
    }

    /* in the following, we have to dispose the object when an error is
     * occured.
     */

    entry = (HPDF_XrefEntry)HPDF_GetMem (xref->mmgr,
            sizeof(HPDF_XrefEntry_Rec));
    if (entry == NULL)
        goto Fail;

    if (HPDF_List_Add(xref->entries, entry) != HPDF_OK) {
        HPDF_FreeMem (xref->mmgr, entry);
        goto Fail;
    }

    entry->entry_typ = HPDF_IN_USE_ENTRY;
    entry->byte_offset = 0;
    entry->gen_no = 0;
    entry->obj = obj;
    header->obj_id = xref->start_offset + xref->entries->count - 1 +
                    HPDF_OTYPE_INDIRECT;

    header->gen_no = entry->gen_no;

    return HPDF_OK;

Fail:
    HPDF_Obj_ForceFree(xref->mmgr, obj);
    return HPDF_Error_GetCode (xref->error);
}
Example #13
0
HPDF_Page
HPDF_Page_New  (HPDF_MMgr   mmgr,
                HPDF_Xref   xref)
{
    HPDF_STATUS ret;
    HPDF_PageAttr attr;
    HPDF_Page page;

    HPDF_PTRACE((" HPDF_Page_New\n"));

    page = HPDF_Dict_New (mmgr);
    if (!page)
        return NULL;

    page->header.obj_class |= HPDF_OSUBCLASS_PAGE;
    page->free_fn = Page_OnFree;
    page->before_write_fn = Page_BeforeWrite;

    attr = HPDF_GetMem (page->mmgr, sizeof(HPDF_PageAttr_Rec));
    if (!attr) {
        HPDF_Dict_Free (page);
        return NULL;
    }

    page->attr = attr;
    HPDF_MemSet (attr, 0, sizeof(HPDF_PageAttr_Rec));
    attr->gmode = HPDF_GMODE_PAGE_DESCRIPTION;
    attr->cur_pos = HPDF_ToPoint (0, 0);
    attr->text_pos = HPDF_ToPoint (0, 0);

    ret = HPDF_Xref_Add (xref, page);
    if (ret != HPDF_OK)
        return NULL;

    attr->gstate = HPDF_GState_New (page->mmgr, NULL);
    attr->contents = HPDF_DictStream_New (page->mmgr, xref);

    if (!attr->gstate || !attr->contents)
        return NULL;

    attr->stream = attr->contents->stream;
    attr->xref = xref;

    /* add requiered elements */
    ret += HPDF_Dict_AddName (page, "Type", "Page");
    ret += HPDF_Dict_Add (page, "MediaBox", HPDF_Box_Array_New (page->mmgr,
                HPDF_ToBox (0, 0, (HPDF_INT16)(HPDF_DEF_PAGE_WIDTH), (HPDF_INT16)(HPDF_DEF_PAGE_HEIGHT))));
    ret += HPDF_Dict_Add (page, "Contents", attr->contents);

    ret += AddResource (page);

    if (ret != HPDF_OK)
        return NULL;

    return page;
}
Example #14
0
static HPDF_STATUS
ReadPngData_Interlaced  (HPDF_Dict    image,
                         png_structp  png_ptr,
                         png_infop    info_ptr)
{
    png_uint_32 len = png_get_rowbytes(png_ptr, info_ptr);
    png_uint_32 height = png_get_image_height(png_ptr, info_ptr);
    png_bytep* row_pointers = HPDF_GetMem (image->mmgr,
                height * sizeof (png_bytep));

    if (row_pointers) {
        HPDF_UINT i;

        HPDF_MemSet (row_pointers, 0, height * sizeof (png_bytep));
        for (i = 0; i < (HPDF_UINT)height; i++) {
            row_pointers[i] = HPDF_GetMem (image->mmgr, len);

            if (image->error->error_no != HPDF_OK)
                break;
        }

        if (image->error->error_no == HPDF_OK) {
            png_read_image(png_ptr, row_pointers);
            if (image->error->error_no == HPDF_OK) {       /* add this line */
                for (i = 0; i < (HPDF_UINT)height; i++) {
                    if (HPDF_Stream_Write (image->stream, row_pointers[i], len) !=
                            HPDF_OK)
                        break;
                }
            }
        }

        /* clean up */
        for (i = 0; i < (HPDF_UINT)height; i++) {
            HPDF_FreeMem (image->mmgr, row_pointers[i]);
        }

        HPDF_FreeMem (image->mmgr, row_pointers);
    }

    return image->error->error_no;
}
Example #15
0
HPDF_NewEx  (HPDF_Error_Handler    user_error_fn,
             HPDF_Alloc_Func       user_alloc_fn,
             HPDF_Free_Func        user_free_fn,
             HPDF_UINT             mem_pool_buf_size,
             void                 *user_data)
{
    HPDF_Doc pdf;
    HPDF_MMgr mmgr;
    HPDF_Error_Rec tmp_error;

    HPDF_PTRACE ((" HPDF_NewEx\n"));

    /* initialize temporary-error object */
    HPDF_Error_Init (&tmp_error, user_data);

    /* create memory-manager object */
    mmgr = HPDF_MMgr_New (&tmp_error, mem_pool_buf_size, user_alloc_fn,
            user_free_fn);
    if (!mmgr) {
        HPDF_CheckError (&tmp_error);
        return NULL;
    }

    /* now create pdf_doc object */
    pdf = HPDF_GetMem (mmgr, sizeof (HPDF_Doc_Rec));
    if (!pdf) {
        HPDF_MMgr_Free (mmgr);
        HPDF_CheckError (&tmp_error);
        return NULL;
    }

    HPDF_MemSet (pdf, 0, sizeof (HPDF_Doc_Rec));
    pdf->sig_bytes = HPDF_SIG_BYTES;
    pdf->mmgr = mmgr;
    pdf->pdf_version = HPDF_VER_13;
    pdf->compression_mode = HPDF_COMP_NONE;

    /* copy the data of temporary-error object to the one which is
       included in pdf_doc object */
    pdf->error = tmp_error;

    /* switch the error-object of memory-manager */
    mmgr->error = &pdf->error;

    if (HPDF_NewDoc (pdf) != HPDF_OK) {
        HPDF_Free (pdf);
        HPDF_CheckError (&tmp_error);
        return NULL;
    }

    pdf->error.error_fn = user_error_fn;

    return pdf;
}
Example #16
0
HPDF_Null
HPDF_Null_New  (HPDF_MMgr  mmgr)
{
    HPDF_Null obj = HPDF_GetMem (mmgr, sizeof(HPDF_Null_Rec));

    if (obj) {
        HPDF_MemSet (&obj->header, 0, sizeof(HPDF_Obj_Header));
        obj->header.obj_class = HPDF_OCLASS_NULL;
    }

    return obj;
}
Example #17
0
static HPDF_STATUS
CreatePallet (HPDF_Dict    image,
              png_structp  png_ptr,
              png_infop    info_ptr)
{
    HPDF_INT num_pl = 0;
    png_color *src_pl = NULL;
    HPDF_BYTE *ppallet;
    HPDF_BYTE *p;
    HPDF_UINT i;
    HPDF_Array array;

    /* png_get_PLTE does not call PngErrorFunc even if it failed.
     * so we call HPDF_Set_Error to set error-code.
     */
    if (png_get_PLTE(png_ptr, info_ptr, (png_color**)&src_pl, &num_pl) !=
            PNG_INFO_PLTE)
        return HPDF_SetError (image->error, HPDF_LIBPNG_ERROR,
                    HPDF_CANNOT_GET_PALLET);


    /* make a pallet array for indexed image. */
    ppallet = HPDF_GetMem (image->mmgr, num_pl * 3);
    if (!ppallet)
        return image->error->error_no;

    p = ppallet;
    for (i = 0; i < num_pl; i++, src_pl++) {
        *p++ = src_pl->red;
        *p++ = src_pl->green;
        *p++ = src_pl->blue;
    }

    array = HPDF_Array_New (image->mmgr);
    if (array) {
        HPDF_Binary b;

        HPDF_Dict_Add (image, "ColorSpace", array);

        HPDF_Array_AddName (array, "Indexed");
        HPDF_Array_AddName (array, "DeviceRGB");
        HPDF_Array_AddNumber (array, num_pl - 1);

        b = HPDF_Binary_New (image->mmgr, ppallet, num_pl * 3);
        if (b)
            HPDF_Array_Add (array, b);
    }

    HPDF_FreeMem (image->mmgr, ppallet);

    return image->error->error_no;
}
Example #18
0
HPDF_Number
HPDF_Number_New  (HPDF_MMgr   mmgr,
                  HPDF_INT32  value)
{
    HPDF_Number obj = (HPDF_Number)HPDF_GetMem (mmgr, sizeof(HPDF_Number_Rec));

    if (obj) {
        HPDF_MemSet (&obj->header, 0, sizeof(HPDF_Obj_Header));
        obj->header.obj_class = HPDF_OCLASS_NUMBER;
        obj->value = value;
    }

    return obj;
}
Example #19
0
HPDF_Real
HPDF_Real_New  (HPDF_MMgr  mmgr,
                HPDF_REAL  value)
{
    HPDF_Real obj = HPDF_GetMem (mmgr, sizeof(HPDF_Real_Rec));

    if (obj) {
        HPDF_MemSet (&obj->header, 0, sizeof(HPDF_Obj_Header));
        obj->header.obj_class = HPDF_OCLASS_REAL;
        obj->error = mmgr->error;
        HPDF_Real_SetValue (obj, value);
    }

    return obj;
}
Example #20
0
HPDF_Proxy
HPDF_Proxy_New  (HPDF_MMgr  mmgr,
                 void       *obj)
{
    HPDF_Proxy p = HPDF_GetMem (mmgr, sizeof(HPDF_Proxy_Rec));

    HPDF_PTRACE((" HPDF_Proxy_New\n"));

    if (p) {
        HPDF_MemSet (&p->header, 0, sizeof(HPDF_Obj_Header));
        p->header.obj_class = HPDF_OCLASS_PROXY;
        p->obj = obj;
    }

    return p;
}
HPDF_STATUS
HPDF_Type1FontDef_SetWidths  (HPDF_FontDef          fontdef,
                              const HPDF_CharData*  widths)
{
    const HPDF_CharData* src = widths;
    HPDF_Type1FontDefAttr attr = (HPDF_Type1FontDefAttr)fontdef->attr;
    HPDF_CharData* dst;
    HPDF_UINT i = 0;

    HPDF_PTRACE (" HPDF_Type1FontDef_SetWidths\n");

    FreeWidth (fontdef);

    while (src->unicode != 0xFFFF) {
        src++;
        i++;
    }

    attr->widths_count = i;

    dst = (HPDF_CharData*)HPDF_GetMem (fontdef->mmgr, sizeof(HPDF_CharData) *
            attr->widths_count);
    if (dst == NULL)
        return HPDF_Error_GetCode (fontdef->error);

    HPDF_MemSet (dst, 0, sizeof(HPDF_CharData) * attr->widths_count);
    attr->widths = dst;

    src = widths;
    for (i = 0; i < attr->widths_count; i++) {
        dst->char_cd = src->char_cd;
        dst->unicode = src->unicode;
        dst->width = src->width;
        if (dst->unicode == 0x0020) {
            fontdef->missing_width = src->width;
        }

        src++;
        dst++;
    }

    return HPDF_OK;
}
Example #22
0
HPDF_Array
HPDF_Array_New  (HPDF_MMgr  mmgr)
{
    HPDF_Array obj;

    HPDF_PTRACE((" HPDF_Array_New\n"));

    obj = HPDF_GetMem (mmgr, sizeof(HPDF_Array_Rec));
    if (obj) {
        HPDF_MemSet (obj, 0, sizeof(HPDF_Array_Rec));
        obj->header.obj_class = HPDF_OCLASS_ARRAY;
        obj->mmgr = mmgr;
        obj->error = mmgr->error;
        obj->list = HPDF_List_New (mmgr, HPDF_DEF_ITEMS_PER_BLOCK);
        if (!obj->list) {
            HPDF_FreeMem (mmgr, obj);
            obj = NULL;
        }
    }

    return obj;
}
Example #23
0
HPDF_STATUS
HPDF_Binary_SetValue  (HPDF_Binary  obj,
                       HPDF_BYTE    *value,
                       HPDF_UINT    len)
{
    if (len > HPDF_LIMIT_MAX_STRING_LEN)
        return HPDF_SetError (obj->error, HPDF_BINARY_LENGTH_ERR, 0);

    if (obj->value) {
        HPDF_FreeMem (obj->mmgr, obj->value);
        obj->len = 0;
    }

    obj->value = HPDF_GetMem (obj->mmgr, len);
    if (!obj->value)
        return HPDF_Error_GetCode (obj->error);

    HPDF_MemCpy (obj->value, value, len);
    obj->len = len;

    return HPDF_OK;
}
Example #24
0
HPDF_List
HPDF_List_New  (HPDF_MMgr  mmgr,
                HPDF_UINT  items_per_block)
{
    HPDF_List list;

    HPDF_PTRACE((" HPDF_List_New\n"));

    if (mmgr == NULL)
        return NULL;

    list = (HPDF_List)HPDF_GetMem (mmgr, sizeof(HPDF_List_Rec));
    if (list) {
        list->mmgr = mmgr;
        list->error = mmgr->error;
        list->block_siz = 0;
        list->items_per_block =
            (items_per_block <= 0 ? HPDF_DEF_ITEMS_PER_BLOCK : items_per_block);
        list->count = 0;
        list->obj = NULL;
    }

    return list;
}
Example #25
0
static HPDF_STATUS
LoadPngData  (HPDF_Dict     image,
              HPDF_Xref     xref,
              HPDF_Stream   png_data,
              HPDF_BOOL     delayed_loading)

{
	HPDF_STATUS ret = HPDF_OK;
	png_uint_32 width, height;
	int bit_depth, color_type;
	png_structp png_ptr = NULL;
	png_infop info_ptr = NULL;

	HPDF_PTRACE ((" HPDF_Image_LoadPngImage\n"));

	/* create read_struct. */
	png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,
			image->error, PngErrorFunc, PngErrorFunc);

	if (png_ptr == NULL) {
		HPDF_SetError (image->error, HPDF_FAILD_TO_ALLOC_MEM, 0);
		return HPDF_FAILD_TO_ALLOC_MEM;
	}

	/* create info-struct */
	info_ptr = png_create_info_struct (png_ptr);

	if (info_ptr == NULL) {
		HPDF_SetError (image->error, HPDF_FAILD_TO_ALLOC_MEM, 0);
		goto Exit;
	}

	png_set_sig_bytes (png_ptr, HPDF_PNG_BYTES_TO_CHECK);
	png_set_read_fn (png_ptr, (void *)png_data, (png_rw_ptr)&PngReadFunc);

	/* reading info structure. */
	png_read_info(png_ptr, info_ptr);
	if (image->error->error_no != HPDF_OK) {
		goto Exit;
	}

	png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);

	/* 16bit images are not supported. */
	if (bit_depth == 16) {
		png_set_strip_16(png_ptr);
	}

	png_read_update_info(png_ptr, info_ptr);
	if (image->error->error_no != HPDF_OK) {
		goto Exit;
	}

	/* check palette-based images for transparent areas and load them immediately if found */
	if (xref && PNG_COLOR_TYPE_PALETTE & color_type) {
		png_bytep trans;
		int num_trans;
		HPDF_Dict smask;
		png_bytep smask_data;

		if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) || 
			!png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL)) {
			goto no_transparent_color_in_palette;
		}

		smask = HPDF_DictStream_New (image->mmgr, xref);
		if (!smask) {
			ret = HPDF_FAILD_TO_ALLOC_MEM;
			goto Exit;
		}

		smask->header.obj_class |= HPDF_OSUBCLASS_XOBJECT;
		ret = HPDF_Dict_AddName (smask, "Type", "XObject");
		ret += HPDF_Dict_AddName (smask, "Subtype", "Image");
		ret += HPDF_Dict_AddNumber (smask, "Width", (HPDF_UINT)width);
		ret += HPDF_Dict_AddNumber (smask, "Height", (HPDF_UINT)height);
		ret += HPDF_Dict_AddName (smask, "ColorSpace", "DeviceGray");
		ret += HPDF_Dict_AddNumber (smask, "BitsPerComponent", (HPDF_UINT)bit_depth);

		if (ret != HPDF_OK) {
			HPDF_Dict_Free(smask);
			ret = HPDF_INVALID_PNG_IMAGE;
			goto Exit;
		}

		smask_data = HPDF_GetMem(image->mmgr, width * height);
		if (!smask_data) {
			HPDF_Dict_Free(smask);
			ret = HPDF_FAILD_TO_ALLOC_MEM;
			goto Exit;
		}

		if (ReadTransparentPaletteData(image, png_ptr, info_ptr, smask_data, trans, num_trans) != HPDF_OK) {
			HPDF_FreeMem(image->mmgr, smask_data);
			HPDF_Dict_Free(smask);
			ret = HPDF_INVALID_PNG_IMAGE;
			goto Exit;
		}

		if (HPDF_Stream_Write(smask->stream, smask_data, width * height) != HPDF_OK) {
			HPDF_FreeMem(image->mmgr, smask_data);
			HPDF_Dict_Free(smask);
			ret = HPDF_FILE_IO_ERROR;
			goto Exit;
		}
		HPDF_FreeMem(image->mmgr, smask_data);


		ret += CreatePallet(image, png_ptr, info_ptr);
		ret += HPDF_Dict_AddNumber (image, "Width", (HPDF_UINT)width);
		ret += HPDF_Dict_AddNumber (image, "Height", (HPDF_UINT)height);
		ret += HPDF_Dict_AddNumber (image, "BitsPerComponent",	(HPDF_UINT)bit_depth);
		ret += HPDF_Dict_Add (image, "SMask", smask);

		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		return HPDF_OK;
	}

no_transparent_color_in_palette:

	/* read images with alpha channel right away 
	   we have to do this because image transparent mask must be added to the Xref */
	if (xref && PNG_COLOR_MASK_ALPHA & color_type) {
		HPDF_Dict smask;
		png_bytep smask_data;

		smask = HPDF_DictStream_New (image->mmgr, xref);
		if (!smask) {
			ret = HPDF_FAILD_TO_ALLOC_MEM;
			goto Exit;
		}

		smask->header.obj_class |= HPDF_OSUBCLASS_XOBJECT;
		ret = HPDF_Dict_AddName (smask, "Type", "XObject");
		ret += HPDF_Dict_AddName (smask, "Subtype", "Image");
		ret += HPDF_Dict_AddNumber (smask, "Width", (HPDF_UINT)width);
		ret += HPDF_Dict_AddNumber (smask, "Height", (HPDF_UINT)height);
		ret += HPDF_Dict_AddName (smask, "ColorSpace", "DeviceGray");
		ret += HPDF_Dict_AddNumber (smask, "BitsPerComponent", (HPDF_UINT)bit_depth);

		if (ret != HPDF_OK) {
			HPDF_Dict_Free(smask);
			ret = HPDF_INVALID_PNG_IMAGE;
			goto Exit;
		}

		smask_data = HPDF_GetMem(image->mmgr, width * height);
		if (!smask_data) {
			HPDF_Dict_Free(smask);
			ret = HPDF_FAILD_TO_ALLOC_MEM;
			goto Exit;
		}

		if (ReadTransparentPngData(image, png_ptr, info_ptr, smask_data) != HPDF_OK) {
			HPDF_FreeMem(image->mmgr, smask_data);
			HPDF_Dict_Free(smask);
			ret = HPDF_INVALID_PNG_IMAGE;
			goto Exit;
		}

		if (HPDF_Stream_Write(smask->stream, smask_data, width * height) != HPDF_OK) {
			HPDF_FreeMem(image->mmgr, smask_data);
			HPDF_Dict_Free(smask);
			ret = HPDF_FILE_IO_ERROR;
			goto Exit;
		}
		HPDF_FreeMem(image->mmgr, smask_data);

		if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
			ret += HPDF_Dict_AddName (image, "ColorSpace", "DeviceGray");
		} else {
			ret += HPDF_Dict_AddName (image, "ColorSpace", "DeviceRGB");
		}
		ret += HPDF_Dict_AddNumber (image, "Width", (HPDF_UINT)width);
		ret += HPDF_Dict_AddNumber (image, "Height", (HPDF_UINT)height);
		ret += HPDF_Dict_AddNumber (image, "BitsPerComponent",	(HPDF_UINT)bit_depth);
		ret += HPDF_Dict_Add (image, "SMask", smask);

		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		return HPDF_OK;
	}

	/* if the image has color palette, copy the pallet of the image to
	 * create color map.
	 */
	if (color_type == PNG_COLOR_TYPE_PALETTE)
		ret = CreatePallet(image, png_ptr, info_ptr);
	else if (color_type == PNG_COLOR_TYPE_GRAY)
		ret = HPDF_Dict_AddName (image, "ColorSpace", "DeviceGray");
	else
		ret = HPDF_Dict_AddName (image, "ColorSpace", "DeviceRGB");

	if (ret != HPDF_OK)
		goto Exit;

	/* read image-data
	 * if the image is interlaced, read whole image at once.
	 * if delayed_loading is HPDF_TRUE, the data does not load this phase.
	 */
	if (delayed_loading) {
		image->before_write_fn = PngBeforeWrite;
		image->after_write_fn = PngAfterWrite;
	} else {
		if (png_get_interlace_type(png_ptr, info_ptr) != PNG_INTERLACE_NONE)
			ret = ReadPngData_Interlaced(image, png_ptr, info_ptr);
		else
			ret = ReadPngData(image, png_ptr, info_ptr);

		if (ret != HPDF_OK)
			goto Exit;
	}

	/* setting the info of the image. */
	if (HPDF_Dict_AddNumber (image, "Width", (HPDF_UINT)width)
			!= HPDF_OK)
		goto Exit;

	if (HPDF_Dict_AddNumber (image, "Height", (HPDF_UINT)height)
			!= HPDF_OK)
		goto Exit;

	if (HPDF_Dict_AddNumber (image, "BitsPerComponent",
				(HPDF_UINT)bit_depth) != HPDF_OK)
		goto Exit;

	/* clean up */
	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

	return HPDF_OK;

Exit:
	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

	if (ret != HPDF_OK) {
		return ret;
	}
	return image->error->error_no;
}
Example #26
0
HPDF_Font
HPDF_TTFont_New  (HPDF_MMgr        mmgr,
                  HPDF_FontDef     fontdef,
                  HPDF_Encoder     encoder,
                  HPDF_Xref        xref)
{
    HPDF_Dict font;
    HPDF_FontAttr attr;
    HPDF_TTFontDefAttr fontdef_attr;
    HPDF_BasicEncoderAttr encoder_attr;
    HPDF_STATUS ret = 0;

    HPDF_PTRACE ((" HPDF_TTFont_New\n"));

    font = HPDF_Dict_New (mmgr);
    if (!font)
        return NULL;

    font->header.obj_class |= HPDF_OSUBCLASS_FONT;

    /* check whether the fontdef object and the encoder object is valid. */
    if (encoder->type != HPDF_ENCODER_TYPE_SINGLE_BYTE) {
        HPDF_SetError(font->error, HPDF_INVALID_ENCODER_TYPE, 0);
        return NULL;
    }

    if (fontdef->type != HPDF_FONTDEF_TYPE_TRUETYPE) {
        HPDF_SetError(font->error, HPDF_INVALID_FONTDEF_TYPE, 0);
        return NULL;
    }

    attr = (HPDF_FontAttr)HPDF_GetMem (mmgr, sizeof(HPDF_FontAttr_Rec));
    if (!attr) {
        HPDF_Dict_Free (font);
        return NULL;
    }

    HPDF_MemSet (attr, 0, sizeof(HPDF_FontAttr_Rec));

    font->header.obj_class |= HPDF_OSUBCLASS_FONT;
    font->write_fn = OnWrite;
    font->before_write_fn = BeforeWrite;
    font->free_fn = OnFree;
    font->attr = attr;

    attr->type = HPDF_FONT_TRUETYPE;
    attr->writing_mode = HPDF_WMODE_HORIZONTAL;
    attr->text_width_fn = TextWidth;
    attr->measure_text_fn = MeasureText;
    attr->fontdef = fontdef;
    attr->encoder = encoder;
    attr->xref = xref;

    /* singlebyte-font has a widths-array which is an array of 256 signed
     * short integer.
     * in the case of type1-font, widths-array for all letters is made in
     * constructer. but in the case of true-type-font, the array is
     * initialized at 0, and set when the corresponding character was used
     * for the first time.
     */
    attr->widths = (HPDF_INT16*)HPDF_GetMem (mmgr, sizeof(HPDF_INT16) * 256);
    if (!attr->widths) {
        HPDF_Dict_Free (font);
        return NULL;
    }

    HPDF_MemSet (attr->widths, 0, sizeof(HPDF_INT16) * 256);

    attr->used = (HPDF_BYTE*)HPDF_GetMem (mmgr, sizeof(HPDF_BYTE) * 256);
    if (!attr->used) {
        HPDF_Dict_Free (font);
        return NULL;
    }

    HPDF_MemSet (attr->used, 0, sizeof(HPDF_BYTE) * 256);

    fontdef_attr = (HPDF_TTFontDefAttr)fontdef->attr;

    ret += HPDF_Dict_AddName (font, "Type", "Font");
    ret += HPDF_Dict_AddName (font, "BaseFont", fontdef_attr->base_font);
    ret += HPDF_Dict_AddName (font, "Subtype", "TrueType");

    encoder_attr = (HPDF_BasicEncoderAttr)encoder->attr;

    ret += HPDF_Dict_AddNumber (font, "FirstChar", encoder_attr->first_char);
    ret += HPDF_Dict_AddNumber (font, "LastChar", encoder_attr->last_char);
    if (fontdef->missing_width != 0)
        ret += HPDF_Dict_AddNumber (font, "MissingWidth",
                fontdef->missing_width);

    if (ret != HPDF_OK) {
        HPDF_Dict_Free (font);
        return NULL;
    }

    if (HPDF_Xref_Add (xref, font) != HPDF_OK)
        return NULL;

    return font;
}
Example #27
0
HPDF_Font
HPDF_Type1Font_New  (HPDF_MMgr        mmgr,
                     HPDF_FontDef     fontdef,
                     HPDF_Encoder     encoder,
                     HPDF_Xref        xref)
{
    HPDF_Dict font;
    HPDF_FontAttr attr;
    HPDF_Type1FontDefAttr fontdef_attr;
    HPDF_BasicEncoderAttr encoder_attr;
    HPDF_STATUS ret = 0;
    HPDF_UINT i;

    HPDF_PTRACE ((" HPDF_Type1Font_New\n"));

    /* check whether the fontdef object and the encoder object is valid. */
    if (encoder->type != HPDF_ENCODER_TYPE_SINGLE_BYTE) {
        HPDF_SetError(mmgr->error, HPDF_INVALID_ENCODER_TYPE, 0);
        return NULL;
    }

    if (fontdef->type != HPDF_FONTDEF_TYPE_TYPE1) {
        HPDF_SetError(mmgr->error, HPDF_INVALID_FONTDEF_TYPE, 0);
        return NULL;
    }

    font = HPDF_Dict_New (mmgr);
    if (!font)
        return NULL;

    font->header.obj_class |= HPDF_OSUBCLASS_FONT;

    attr = HPDF_GetMem (mmgr, sizeof(HPDF_FontAttr_Rec));
    if (!attr) {
        HPDF_Dict_Free (font);
        return NULL;
    }

    font->header.obj_class |= HPDF_OSUBCLASS_FONT;
    font->write_fn = Type1Font_OnWrite;
    font->free_fn = Type1Font_OnFree;

    HPDF_MemSet (attr, 0, sizeof(HPDF_FontAttr_Rec));

    font->attr = attr;
    attr->type = HPDF_FONT_TYPE1;
    attr->writing_mode = HPDF_WMODE_HORIZONTAL;
    attr->text_width_fn = Type1Font_TextWidth;
    attr->measure_text_fn = Type1Font_MeasureText;
    attr->fontdef = fontdef;
    attr->encoder = encoder;
    attr->xref = xref;

    /* singlebyte-font has a widths-array which is an array of 256 signed
     * short integer.
     */
    attr->widths = HPDF_GetMem (mmgr, sizeof(HPDF_INT16) * 256);
    if (!attr->widths) {
        HPDF_Dict_Free (font);
        return NULL;
    }

    encoder_attr = (HPDF_BasicEncoderAttr)encoder->attr;

    HPDF_MemSet (attr->widths, 0, sizeof(HPDF_INT16) * 256);
    for (i = encoder_attr->first_char; i <= encoder_attr->last_char; i++) {
        HPDF_UNICODE u = encoder_attr->unicode_map[i];

        HPDF_UINT16 w = HPDF_Type1FontDef_GetWidth (fontdef, u);
        attr->widths[i] = w;
    }

    fontdef_attr = (HPDF_Type1FontDefAttr)fontdef->attr;

    if(strncmp (fontdef->base_font, "HPDF_", 5) == 0 && fontdef->is_form_font == HPDF_TRUE)
    {
        ret += HPDF_Dict_AddName (font, "Type", "Font");
        ret += HPDF_Dict_AddName (font, "BaseFont", fontdef->base_font + 5);
        ret += HPDF_Dict_AddName (font, "Subtype", "TrueType");
    }
    else{
        ret += HPDF_Dict_AddName (font, "Type", "Font");
        ret += HPDF_Dict_AddName (font, "BaseFont", fontdef->base_font);
        ret += HPDF_Dict_AddName (font, "Subtype", "Type1");
    }
    if (!fontdef_attr->is_base14font) {
        if (fontdef->missing_width != 0)
            ret += HPDF_Dict_AddNumber (font, "MissingWidth",
                    fontdef->missing_width);

        ret += Type1Font_CreateDescriptor (mmgr, font, xref);
    }

    if (ret != HPDF_OK) {
        HPDF_Dict_Free (font);
        return NULL;
    }

    if (HPDF_Xref_Add (xref, font) != HPDF_OK)
        return NULL;

    return font;
}
Example #28
0
static HPDF_STATUS
ReadTransparentPngData  (HPDF_Dict    image,
                         png_structp  png_ptr,
                         png_infop    info_ptr,
                         png_bytep    smask_data)
{
	HPDF_STATUS ret = HPDF_OK;
	HPDF_INT row_len;
	HPDF_UINT i, j;
	png_bytep *row_ptr, row = 0;
	png_byte color_type;
	png_uint_32 height = png_get_image_height(png_ptr, info_ptr);
	png_uint_32 width = png_get_image_width(png_ptr, info_ptr);

	color_type = png_get_color_type(png_ptr, info_ptr);

	if (!(color_type & PNG_COLOR_MASK_ALPHA)) {
		return HPDF_INVALID_PNG_IMAGE;
	}

	row_ptr = HPDF_GetMem (image->mmgr, height * sizeof(png_bytep));
	if (!row_ptr) {
		return HPDF_FAILD_TO_ALLOC_MEM;
	} else {
		png_uint_32 len = png_get_rowbytes(png_ptr, info_ptr);

		for (i = 0; i < (HPDF_UINT)height; i++) {
			row_ptr[i] = HPDF_GetMem(image->mmgr, len);
			if (!row_ptr[i]) {
				for (; i > 0; i--) {
					HPDF_FreeMem (image->mmgr, row_ptr[i]);
				}
				HPDF_FreeMem (image->mmgr, row_ptr);
				return HPDF_FAILD_TO_ALLOC_MEM;
			}
		}
	}

	png_read_image(png_ptr, row_ptr);
	if (image->error->error_no != HPDF_OK) {
		ret = HPDF_INVALID_PNG_IMAGE;
		goto Error;
	}

	switch (color_type) {
		case PNG_COLOR_TYPE_RGB_ALPHA:
			row_len = 3 * width * sizeof(png_byte);
			for (j = 0; j < height; j++) {
				for (i = 0; i < width; i++) {
					row = row_ptr[j];
					memmove(row + (3 * i), row + (4*i), 3);
					smask_data[width * j + i] = row[4 * i + 3];
				}

				if (HPDF_Stream_Write (image->stream, row, row_len) != HPDF_OK) {
					ret = HPDF_FILE_IO_ERROR;
					goto Error;
				}
			}
			break;
		case PNG_COLOR_TYPE_GRAY_ALPHA:
			row_len = width * sizeof(png_byte);
			for (j = 0; j < height; j++) {
				for (i = 0; i < width; i++) {
					row = row_ptr[j];
					row[i] = row[2 * i];
					smask_data[width * j + i] = row[2 * i + 1];
				}

				if (HPDF_Stream_Write (image->stream, row, row_len) != HPDF_OK) {
					ret = HPDF_FILE_IO_ERROR;
					goto Error;
				}
			}
			break;
		default:
			ret = HPDF_INVALID_PNG_IMAGE;
			goto Error;
	}

Error:
	for (i = 0; i < (HPDF_UINT)height; i++) {
		HPDF_FreeMem (image->mmgr, row_ptr[i]);
	}

	HPDF_FreeMem (image->mmgr, row_ptr);
	return ret;
}
Example #29
0
HPDF_Font
HPDF_Type0Font_New  (HPDF_MMgr        mmgr,
                     HPDF_FontDef     fontdef,
                     HPDF_Encoder     encoder,
                     HPDF_Xref        xref)
{
    HPDF_Dict font;
    HPDF_FontAttr attr;
    HPDF_CMapEncoderAttr encoder_attr;
    HPDF_STATUS ret = 0;
    HPDF_Array descendant_fonts;

    HPDF_PTRACE ((" HPDF_Type0Font_New\n"));

    font = HPDF_Dict_New (mmgr);
    if (!font)
        return NULL;

    font->header.obj_class |= HPDF_OSUBCLASS_FONT;

    /* check whether the fontdef object and the encoder object is valid. */
    if (encoder->type != HPDF_ENCODER_TYPE_DOUBLE_BYTE) {
        HPDF_SetError(font->error, HPDF_INVALID_ENCODER_TYPE, 0);
        return NULL;
    }

    if (fontdef->type != HPDF_FONTDEF_TYPE_CID &&
        fontdef->type != HPDF_FONTDEF_TYPE_TRUETYPE) {
        HPDF_SetError(font->error, HPDF_INVALID_FONTDEF_TYPE, 0);
        return NULL;
    }

    attr = HPDF_GetMem (mmgr, sizeof(HPDF_FontAttr_Rec));
    if (!attr) {
        HPDF_Dict_Free (font);
        return NULL;
    }

    font->header.obj_class |= HPDF_OSUBCLASS_FONT;
    font->write_fn = NULL;
    font->free_fn = OnFree_Func;
    font->attr = attr;

    encoder_attr = (HPDF_CMapEncoderAttr)encoder->attr;

    HPDF_MemSet (attr, 0, sizeof(HPDF_FontAttr_Rec));

    attr->writing_mode = encoder_attr->writing_mode;
    attr->text_width_fn = TextWidth;
    attr->measure_text_fn = MeasureText;
    attr->fontdef = fontdef;
    attr->encoder = encoder;
    attr->xref = xref;

    if (HPDF_Xref_Add (xref, font) != HPDF_OK)
        return NULL;

    ret += HPDF_Dict_AddName (font, "Type", "Font");
    ret += HPDF_Dict_AddName (font, "BaseFont", fontdef->base_font);
    ret += HPDF_Dict_AddName (font, "Subtype", "Type0");

    if (fontdef->type == HPDF_FONTDEF_TYPE_CID) {
        ret += HPDF_Dict_AddName (font, "Encoding", encoder->name);
    } else {
        /*
	 * Handle the Unicode encoding, see hpdf_encoding_utf.c For some
	 * reason, xpdf-based readers cannot deal with our cmap but work
	 * fine when using the predefined "Identity-H"
	 * encoding. However, text selection does not work, unless we
	 * add a ToUnicode cmap. This CMap should also be "Identity",
	 * but that does not work -- specifying our cmap as a stream however
	 * does work. Who can understand that ?
	 */
        if (HPDF_StrCmp(encoder_attr->ordering, "Identity-H") == 0) {
	    ret += HPDF_Dict_AddName (font, "Encoding", "Identity-H");
	    attr->cmap_stream = CreateCMap (encoder, xref);

	    if (attr->cmap_stream) {
	        ret += HPDF_Dict_Add (font, "ToUnicode", attr->cmap_stream);
	    } else
	        return NULL;
	} else {
            attr->cmap_stream = CreateCMap (encoder, xref);

	    if (attr->cmap_stream) {
	        ret += HPDF_Dict_Add (font, "Encoding", attr->cmap_stream);
	    } else
	      return NULL;
	}
    }

    if (ret != HPDF_OK)
        return NULL;

    descendant_fonts = HPDF_Array_New (mmgr);
    if (!descendant_fonts)
        return NULL;

    if (HPDF_Dict_Add (font, "DescendantFonts", descendant_fonts) != HPDF_OK)
        return NULL;

    if (fontdef->type == HPDF_FONTDEF_TYPE_CID) {
        attr->descendant_font = CIDFontType0_New (font, xref);
        attr->type = HPDF_FONT_TYPE0_CID;
    } else {
        attr->descendant_font = CIDFontType2_New (font, xref);
        attr->type = HPDF_FONT_TYPE0_TT;
    }

    if (!attr->descendant_font)
        return NULL;
    else
        if (HPDF_Array_Add (descendant_fonts, attr->descendant_font) !=
                HPDF_OK)
            return NULL;

    return font;
}
static HPDF_STATUS
LoadAfm (HPDF_FontDef  fontdef,
         HPDF_Stream   stream)
{
    HPDF_Type1FontDefAttr attr = (HPDF_Type1FontDefAttr)fontdef->attr;
    char buf[HPDF_TMP_BUF_SIZ];
    HPDF_CharData* cdata;
    HPDF_STATUS ret;
    HPDF_UINT len;
    char keyword[HPDF_LIMIT_MAX_NAME_LEN + 1];
    HPDF_UINT i;

    HPDF_PTRACE (" LoadAfm\n");

    len = HPDF_TMP_BUF_SIZ;

    /* chaeck AFM header */
    if ((ret = HPDF_Stream_ReadLn (stream, buf, &len)) != HPDF_OK)
         return ret;

    GetKeyword (buf, keyword, HPDF_LIMIT_MAX_NAME_LEN + 1);

    if (HPDF_StrCmp (keyword, "StartFontMetrics") != 0)
        return HPDF_INVALID_AFM_HEADER;

    /* Global Font Information */

    for (;;) {
        const char *s;

        len = HPDF_TMP_BUF_SIZ;
        if ((ret = HPDF_Stream_ReadLn (stream, buf, &len)) != HPDF_OK)
            return ret;

        s = GetKeyword (buf, keyword, HPDF_LIMIT_MAX_NAME_LEN + 1);

        if (HPDF_StrCmp (keyword, "FontName") == 0) {
            HPDF_StrCpy (fontdef->base_font, s,
                    fontdef->base_font + HPDF_LIMIT_MAX_NAME_LEN);
        } else

        if (HPDF_StrCmp (keyword, "Weight") == 0) {
            if (HPDF_StrCmp (s, "Bold") == 0)
                fontdef->flags |= HPDF_FONT_FOURCE_BOLD;
        } else

        if (HPDF_StrCmp (keyword, "IsFixedPitch") == 0) {
            if (HPDF_StrCmp (s, "true") == 0)
               fontdef->flags |= HPDF_FONT_FIXED_WIDTH;
        } else

        if (HPDF_StrCmp (keyword, "ItalicAngle") == 0) {
            fontdef->italic_angle = (HPDF_INT16)HPDF_AToI (s);
            if (fontdef->italic_angle != 0)
                fontdef->flags |= HPDF_FONT_ITALIC;
        } else

        if (HPDF_StrCmp (keyword, "CharacterSet") == 0) {
            HPDF_UINT len = HPDF_StrLen (s, HPDF_LIMIT_MAX_STRING_LEN);

            if (len > 0) {
                attr->char_set = HPDF_GetMem (fontdef->mmgr, len + 1);
                if (!attr->char_set)
                    return HPDF_Error_GetCode (fontdef->error);

                HPDF_StrCpy (attr->char_set, s, attr->char_set + len);
            }
        } else
        if (HPDF_StrCmp (keyword, "FontBBox") == 0) {
            char buf[HPDF_INT_LEN + 1];

            s = GetKeyword (s, buf, HPDF_INT_LEN + 1);
            fontdef->font_bbox.left = (HPDF_REAL)HPDF_AToI (buf);

            s = GetKeyword (s, buf, HPDF_INT_LEN + 1);
            fontdef->font_bbox.bottom = (HPDF_REAL)HPDF_AToI (buf);

            s = GetKeyword (s, buf, HPDF_INT_LEN + 1);
            fontdef->font_bbox.right = (HPDF_REAL)HPDF_AToI (buf);

            GetKeyword (s, buf, HPDF_INT_LEN + 1);
            fontdef->font_bbox.top = (HPDF_REAL)HPDF_AToI (buf);
        } else
        if (HPDF_StrCmp (keyword, "EncodingScheme") == 0) {
            HPDF_StrCpy (attr->encoding_scheme, s,
                    attr->encoding_scheme + HPDF_LIMIT_MAX_NAME_LEN);
        } else
        if (HPDF_StrCmp (keyword, "CapHeight") == 0) {
            fontdef->cap_height = (HPDF_UINT16)HPDF_AToI (s);
        } else
        if (HPDF_StrCmp (keyword, "Ascender") == 0) {
            fontdef->ascent = (HPDF_INT16)HPDF_AToI (s);
        } else
        if (HPDF_StrCmp (keyword, "Descender") == 0) {
            fontdef->descent = (HPDF_INT16)HPDF_AToI (s);
        } else
        if (HPDF_StrCmp (keyword, "STDHW") == 0) {
            fontdef->stemh = (HPDF_UINT16)HPDF_AToI (s);
        } else
        if (HPDF_StrCmp (keyword, "STDHV") == 0) {
            fontdef->stemv = (HPDF_UINT16)HPDF_AToI (s);
        } else
        if (HPDF_StrCmp (keyword, "StartCharMetrics") == 0) {
            attr->widths_count = HPDF_AToI (s);
            break;
        }
    }

    cdata = (HPDF_CharData*)HPDF_GetMem (fontdef->mmgr,
            sizeof(HPDF_CharData) * attr->widths_count);
    if (cdata == NULL)
        return HPDF_Error_GetCode (fontdef->error);

    HPDF_MemSet (cdata, 0, sizeof(HPDF_CharData) * attr->widths_count);
    attr->widths = cdata;

    /* load CharMetrics */
    for (i = 0; i < attr->widths_count; i++, cdata++) {
        const char *s;
        char buf2[HPDF_LIMIT_MAX_NAME_LEN + 1];

        len = HPDF_TMP_BUF_SIZ;
        if ((ret = HPDF_Stream_ReadLn (stream, buf, &len)) != HPDF_OK)
            return ret;

        /* C default character code. */
        s = GetKeyword (buf, buf2, HPDF_LIMIT_MAX_NAME_LEN + 1);
        if (HPDF_StrCmp (buf2, "CX") == 0) {
            /* not suppoted yet. */
            return HPDF_SetError (fontdef->error,
                    HPDF_INVALID_CHAR_MATRICS_DATA, 0);
        } else
        if (HPDF_StrCmp (buf2, "C") == 0) {
            s += 2;

            s = GetKeyword (s, buf2, HPDF_LIMIT_MAX_NAME_LEN + 1);
              HPDF_AToI (buf2);

            cdata->char_cd = (HPDF_INT16)HPDF_AToI (buf2);

        } else
            return HPDF_SetError (fontdef->error,
                    HPDF_INVALID_CHAR_MATRICS_DATA, 0);

        /* WX Character width */
        s = HPDF_StrStr (s, "WX ", 0);
        if (!s)
            return HPDF_SetError (fontdef->error, HPDF_INVALID_WX_DATA, 0);

        s += 3;

        s = GetKeyword (s, buf2, HPDF_LIMIT_MAX_NAME_LEN + 1);
        if (buf2[0] == 0)
            return HPDF_SetError (fontdef->error, HPDF_INVALID_WX_DATA, 0);

        cdata->width = (HPDF_INT16)HPDF_AToI (buf2);

        /* N PostScript language character name */
        s = HPDF_StrStr (s, "N ", 0);
        if (!s)
            return HPDF_SetError (fontdef->error, HPDF_INVALID_N_DATA, 0);

        s += 2;

        GetKeyword (s, buf2, HPDF_LIMIT_MAX_NAME_LEN + 1);

        cdata->unicode = HPDF_GryphNameToUnicode (buf2);

    }

    return HPDF_OK;
}