Back to index

texmacs  1.0.7.15
pdfresource.c
Go to the documentation of this file.
00001 /*  $Header: /home/cvsroot/dvipdfmx/src/pdfresource.c,v 1.9 2008/11/30 21:12:27 matthias Exp $
00002 
00003     This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
00004 
00005     Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata,
00006     the dvipdfmx project team <dvipdfmx@project.ktug.or.kr>
00007 
00008     Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks@kettering.edu>
00009 
00010     This program is free software; you can redistribute it and/or modify
00011     it under the terms of the GNU General Public License as published by
00012     the Free Software Foundation; either version 2 of the License, or
00013     (at your option) any later version.
00014 
00015     This program is distributed in the hope that it will be useful,
00016     but WITHOUT ANY WARRANTY; without even the implied warranty of
00017     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018     GNU General Public License for more details.
00019 
00020     You should have received a copy of the GNU General Public License
00021     along with this program; if not, write to the Free Software
00022     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00023 */
00024 
00025 /*
00026  * Currently, this is nearly useless.
00027  */
00028 
00029 #if HAVE_CONFIG_H
00030 #include "config.h"
00031 #endif
00032 
00033 #include "system.h"
00034 #include "mem.h"
00035 #include "error.h"
00036 
00037 #include "dpxutil.h"
00038 
00039 #include "pdfobj.h"
00040 
00041 #include "pdfresource.h"
00042 
00043 #define PDF_RESOURCE_DEBUG_STR "PDF"
00044 #define PDF_RESOURCE_DEBUG     3
00045 
00046 #define PDF_RESOURCE_FONT       0
00047 #define PDF_RESOURCE_CIDFONT    1
00048 #define PDF_RESOURCE_ENCODING   2
00049 #define PDF_RESOURCE_CMAP       3
00050 #define PDF_RESOURCE_XOBJECT    4
00051 #define PDF_RESOURCE_COLORSPACE 5
00052 #define PDF_RESOURCE_SHADING    6
00053 #define PDF_RESOURCE_PATTERN    7
00054 #define PDF_RESOURCE_GSTATE     8
00055 
00056 typedef struct pdf_res
00057 {
00058   char    *ident;
00059 
00060   int      flags;
00061 
00062   int      category;
00063   void    *cdata;
00064 
00065   pdf_obj *object;
00066   pdf_obj *reference;
00067 } pdf_res;
00068 
00069 static struct {
00070   const char *name;
00071   int         cat_id;
00072 } pdf_resource_categories[] = {
00073   {"Font",       PDF_RESOURCE_FONT},
00074   {"CIDFont",    PDF_RESOURCE_CIDFONT},
00075   {"Encoding",   PDF_RESOURCE_ENCODING},
00076   {"CMap",       PDF_RESOURCE_CMAP},
00077   {"XObject",    PDF_RESOURCE_XOBJECT},
00078   {"ColorSpace", PDF_RESOURCE_COLORSPACE},
00079   {"Shading",    PDF_RESOURCE_SHADING},
00080   {"Pattern",    PDF_RESOURCE_PATTERN},
00081   {"ExtGState",  PDF_RESOURCE_GSTATE},
00082 };
00083 
00084 #define PDF_NUM_RESOURCE_CATEGORIES (sizeof(pdf_resource_categories)/sizeof(pdf_resource_categories[0]))
00085 
00086 #define CACHE_ALLOC_SIZE 16u
00087 struct res_cache
00088 {
00089   int      count;
00090   int      capacity;
00091   pdf_res *resources;
00092 };
00093 
00094 static struct res_cache resources[PDF_NUM_RESOURCE_CATEGORIES];
00095 
00096 static void
00097 pdf_init_resource (pdf_res *res)
00098 {
00099   ASSERT(res);
00100 
00101   res->ident     = NULL;
00102   res->category  = -1;
00103   res->flags     = 0;
00104   res->cdata     = NULL;
00105   res->object    = NULL;
00106   res->reference = NULL;
00107 
00108   return;
00109 }
00110 
00111 static void
00112 pdf_flush_resource (pdf_res *res)
00113 {
00114   if (res) {
00115     if (res->reference)
00116       pdf_release_obj(res->reference);
00117     if (res->object)
00118       pdf_release_obj(res->object);
00119 
00120     res->reference = NULL;
00121     res->object    = NULL;
00122   }
00123 }
00124 
00125 static void
00126 pdf_clean_resource (pdf_res *res)
00127 {
00128   if (res) {
00129     if (res->reference || res->object)
00130       WARN("Trying to release un-flushed object.");
00131     if (res->reference)
00132       pdf_release_obj(res->reference);
00133     if (res->object)
00134       pdf_release_obj(res->object);
00135     if (res->ident)
00136       RELEASE(res->ident);
00137     res->ident    = NULL;
00138     res->category = -1;
00139     res->flags    = 0;
00140   }
00141 }
00142 
00143 void
00144 pdf_init_resources (void)
00145 {
00146   int  i;
00147 
00148   for (i = 0;
00149        i < PDF_NUM_RESOURCE_CATEGORIES; i++) {
00150     resources[i].count     = 0;
00151     resources[i].capacity  = 0;
00152     resources[i].resources = NULL;
00153   }
00154 }
00155 
00156 void
00157 pdf_close_resources (void)
00158 {
00159   int  i;
00160 
00161   for (i = 0;
00162        i < PDF_NUM_RESOURCE_CATEGORIES; i++) {
00163     struct res_cache *rc;
00164     int    j;
00165 
00166     rc = &resources[i];
00167     for (j = 0; j < rc->count; j++) {
00168       pdf_flush_resource(&rc->resources[j]);
00169       pdf_clean_resource(&rc->resources[j]);
00170     }
00171     RELEASE(rc->resources);
00172 
00173     rc->count     = 0;
00174     rc->capacity  = 0;
00175     rc->resources = NULL;
00176   }
00177 }
00178 
00179 static int
00180 get_category (const char *category)
00181 {
00182   int  i;
00183 
00184   for (i = 0;
00185        i < PDF_NUM_RESOURCE_CATEGORIES; i++) {
00186     if (!strcmp(category, pdf_resource_categories[i].name)) {
00187       return pdf_resource_categories[i].cat_id;
00188     }
00189   }
00190 
00191   return -1;
00192 }
00193 
00194 long
00195 pdf_defineresource (const char *category,
00196                   const char *resname, pdf_obj *object, int flags)
00197 {
00198   int      res_id;
00199   struct res_cache *rc;
00200   int      cat_id;
00201   pdf_res *res = NULL;
00202 
00203   ASSERT(category && object);
00204 
00205   cat_id = get_category(category);
00206   if (cat_id < 0) {
00207     ERROR("Unknown resource category: %s", category);
00208     return -1;
00209   }
00210 
00211   rc = &resources[cat_id];
00212   if (resname) {
00213     for (res_id = 0; res_id < rc->count; res_id++) {
00214       res = &rc->resources[res_id];
00215       if (!strcmp(resname, res->ident)) {
00216        WARN("Resource %s (category: %s) already defined...",
00217             resname, category);
00218        pdf_flush_resource(res);
00219        res->flags    = flags;
00220        if (flags & PDF_RES_FLUSH_IMMEDIATE) {
00221          res->reference = pdf_ref_obj(object);
00222          pdf_release_obj(object);
00223        } else {
00224          res->object = object;
00225        }
00226        return (long) ((cat_id << 16)|(res_id));
00227       }
00228     }
00229   } else {
00230     res_id = rc->count;
00231   }
00232 
00233   if (res_id == rc->count) {
00234     if (rc->count >= rc->capacity) {
00235       rc->capacity += CACHE_ALLOC_SIZE;
00236       rc->resources = RENEW(rc->resources, rc->capacity, pdf_res);
00237     }
00238     res = &rc->resources[res_id];
00239 
00240     pdf_init_resource(res);
00241     if (resname && resname[0] != '\0') {
00242       res->ident = NEW(strlen(resname) + 1, char);
00243       strcpy(res->ident, resname);
00244     }
00245     res->category = cat_id;
00246     res->flags    = flags;
00247     if (flags & PDF_RES_FLUSH_IMMEDIATE) {
00248       res->reference = pdf_ref_obj(object);
00249       pdf_release_obj(object);
00250     } else {
00251       res->object = object;
00252     }
00253     rc->count++;
00254   }
00255 
00256   return (long) ((cat_id << 16)|(res_id));
00257 }
00258 
00259 #if 0
00260 int
00261 pdf_resource_exist (const char *category, const char *resname)
00262 {
00263   int    res_id;
00264   struct res_cache *rc;
00265   int    cat_id;
00266 
00267   ASSERT(resname && category);
00268 
00269   cat_id = get_category(category);
00270   if (cat_id < 0)
00271     ERROR("Unknown resource category: %s", category);
00272 
00273   rc = &resources[cat_id];
00274   for (res_id = 0; res_id < rc->count; res_id++) {
00275     pdf_res *res;
00276 
00277     res = &rc->resources[res_id];
00278     if (!strcmp(resname, res->ident)) {
00279       return 1;
00280     }
00281   }
00282 
00283   return 0;
00284 }
00285 #endif
00286 
00287 long
00288 pdf_findresource (const char *category, const char *resname)
00289 {
00290   pdf_res *res;
00291   int      res_id, cat_id;
00292   struct res_cache *rc;
00293 
00294   ASSERT(resname && category);
00295 
00296   cat_id = get_category(category);
00297   if (cat_id < 0) {
00298     ERROR("Unknown resource category: %s", category);
00299     return -1;
00300   }
00301 
00302   rc = &resources[cat_id];
00303   for (res_id = 0; res_id < rc->count; res_id++) {
00304     res = &rc->resources[res_id];
00305     if (!strcmp(resname, res->ident)) {
00306       return (long) (cat_id << 16|res_id);
00307     }
00308   }
00309 
00310   return -1;
00311 }
00312 
00313 pdf_obj *
00314 pdf_get_resource_reference (long rc_id)
00315 {
00316   int  cat_id, res_id;
00317   struct res_cache *rc;
00318   pdf_res *res;
00319 
00320   cat_id = (rc_id >> 16) & 0xffff;
00321   res_id = rc_id & 0xffff;
00322 
00323   if (cat_id < 0 ||
00324       cat_id >= PDF_NUM_RESOURCE_CATEGORIES) {
00325     ERROR("Invalid category ID: %d", cat_id);
00326     return NULL;
00327   }
00328   rc  = &resources[cat_id];
00329   if (res_id < 0 || res_id >= rc->count) {
00330     ERROR("Invalid resource ID: %d", res_id);
00331     return NULL;
00332   }
00333 
00334   res = &rc->resources[res_id];
00335   if (!res->reference) {
00336     if (!res->object) {
00337       ERROR("Undefined object...");
00338       return NULL;
00339     } else {
00340       res->reference = pdf_ref_obj(res->object);
00341     }
00342   }
00343 
00344   return pdf_link_obj(res->reference);
00345 }
00346 
00347 #if 0
00348 pdf_obj *
00349 pdf_get_resource (long rc_id)
00350 {
00351   int  cat_id, res_id;
00352   struct res_cache *rc;
00353   pdf_res *res;
00354 
00355   cat_id = (rc_id >> 16) & 0xffff;
00356   res_id = rc_id & 0xffff;
00357 
00358   if (cat_id < 0 ||
00359       cat_id >= PDF_NUM_RESOURCE_CATEGORIES) {
00360     ERROR("Invalid category ID: %d", cat_id);
00361     return NULL;
00362   }
00363   rc  = &resources[cat_id];
00364   if (res_id < 0 || res_id >= rc->count) {
00365     ERROR("Invalid resource ID: %d", res_id);
00366     return NULL;
00367   }
00368 
00369   res = &rc->resources[res_id];
00370   if (!res->object) {
00371     ERROR("Object already flushed???");
00372     return NULL;
00373   }
00374 
00375   return res->object;
00376 }
00377 #endif