[gs-cvs] gs/src
Igor Melichev
igor at ghostscript.com
Mon Nov 17 08:42:50 PST 2003
Update of /cvs/ghostscript/gs/src
In directory casper:/tmp/cvs-serv11440/gs/src
Modified Files:
gsfont.c gxfill.c gxttfb.c gx.h gxfcache.h gxfdrop.h lib.mak
Added Files:
gzspotan.c gzspotan.h
Log Message:
Implementing a True Type grid fitting, step 1.
DETAILS :
It's an initial commitment.
It is not completed, but we need to store changes to lib.mak .
The new code is disabled with TT_GRID_FITTING 0 in gx.h .
EXPECTED DIFFERENCES :
None.
--- NEW FILE: gzspotan.c ---
/* Copyright (C) 2003 Aladdin Enterprises. All rights reserved.
This software is provided AS-IS with no warranty, either express or
implied.
This software is distributed under license and may not be copied,
modified or distributed except as expressly authorized under the terms
of the license contained in the file LICENSE in this distribution.
For more information about licensing, please refer to
http://www.ghostscript.com/licensing/. For information on
commercial licensing, go to http://www.artifex.com/licensing/ or
contact Artifex Software, Inc., 101 Lucas Valley Road #110,
San Rafael, CA 94903, U.S.A., +1(415)492-9861.
*/
/*$Id: gzspotan.c,v 1.1 2003/11/17 16:42:48 igor Exp $ */
/* A spot analyzer device implementation. */
#include "gx.h"
#include "gserrors.h"
#include "gsdevice.h"
#include "gzspotan.h"
#include "gxfixed.h"
#include "gxdevice.h"
#include "memory_.h"
#include "vdtrace.h"
#include <assert.h>
#define VD_TRAP_N_COLOR RGB(128, 128, 0)
#define VD_TRAP_U_COLOR RGB(0, 0, 255)
#define VD_CONT_COLOR RGB(0, 255, 0)
public_st_device_spot_analyzer();
private_st_san_trap();
private_st_san_trap_contact();
private dev_proc_open_device(san_open);
private dev_proc_close_device(san_close);
private dev_proc_get_clipping_box(san_get_clipping_box);
/* The device descriptor */
/* Many of these procedures won't be called; they are set to NULL. */
private const gx_device_spot_analyzer gx_spot_analyzer_device =
{std_device_std_body(gx_device_spot_analyzer, 0, "spot analyzer",
0, 0, 1, 1),
{san_open,
NULL,
NULL,
NULL,
san_close,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
gx_default_fill_path,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
san_get_clipping_box,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
gx_default_finish_copydevice,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
}
};
private int
san_open(register gx_device * dev)
{
gx_device_spot_analyzer * const padev = (gx_device_spot_analyzer *)dev;
padev->trap_buffer = 0;
padev->cont_buffer = 0;
padev->trap_buffer_count = padev->trap_buffer_max = 0;
padev->cont_buffer_count = padev->cont_buffer_max = 0;
return 0;
}
private int
san_close(gx_device * dev)
{
gx_device_spot_analyzer * const padev = (gx_device_spot_analyzer *)dev;
gs_free_object(padev->memory, padev->trap_buffer, "san_close");
padev->trap_buffer = 0;
gs_free_object(padev->memory, padev->cont_buffer, "san_close");
padev->cont_buffer = 0;
return 0;
}
void
san_get_clipping_box(gx_device * dev, gs_fixed_rect * pbox)
{
pbox->p.x = min_int;
pbox->p.y = min_int;
pbox->q.x = max_int;
pbox->q.y = max_int;
}
/* --------------------- Utilities ------------------------- */
/* fixme : use something like C++ patterns to generate same functions for various types. */
private const int buf_increment = 100;
private inline gx_san_trap *
trap_reserve(gx_device_spot_analyzer *padev)
{
if (padev->trap_buffer_count == padev->trap_buffer_max) {
gx_san_trap *buf = gs_alloc_struct_array(padev->memory,
padev->trap_buffer_max + buf_increment, gx_san_trap,
&st_san_trap, "trap_reserve");
if (buf == NULL)
return NULL;
if (padev->trap_buffer != NULL) {
memcpy(buf, padev->trap_buffer, sizeof(buf[0]) * padev->trap_buffer_max);
gs_free_object(padev->memory, padev->trap_buffer, "trap_reserve");
}
padev->trap_buffer = buf;
padev->trap_buffer_max += buf_increment;
}
return &padev->trap_buffer[padev->trap_buffer_count++];
}
private inline gx_san_trap_contact *
cont_reserve(gx_device_spot_analyzer *padev)
{
if (padev->cont_buffer_count == padev->cont_buffer_max) {
gx_san_trap_contact *buf = gs_alloc_struct_array(padev->memory,
padev->cont_buffer_max + buf_increment, gx_san_trap_contact,
&st_san_trap_contact, "cont_reserve");
if (buf == NULL)
return NULL;
if (padev->cont_buffer != NULL) {
memcpy(buf, padev->cont_buffer, sizeof(buf[0]) * padev->cont_buffer_max);
gs_free_object(padev->memory, padev->cont_buffer, "cont_reserve");
}
padev->cont_buffer = buf;
padev->cont_buffer_max += buf_increment;
}
return &padev->cont_buffer[padev->cont_buffer_count++];
}
private inline void
trap_unreserve(gx_device_spot_analyzer *padev, gx_san_trap *t)
{
assert(t == &padev->trap_buffer[padev->trap_buffer_count - 1]);
padev->trap_buffer_count--;
}
private inline void
cont_unreserve(gx_device_spot_analyzer *padev, gx_san_trap_contact *t)
{
assert(t == &padev->cont_buffer[padev->cont_buffer_count - 1]);
padev->cont_buffer_count--;
}
private inline gx_san_trap *
band_list_last(const gx_san_trap *list)
{
/* Assuming a non-empty cyclic list, and the anchor points to the first element. */
return list->prev;
}
private inline gx_san_trap_contact *
cont_list_last(const gx_san_trap_contact *list)
{
/* Assuming a non-empty cyclic list, and the anchor points to the first element. */
return list->prev;
}
private inline void
band_list_remove(gx_san_trap **list, gx_san_trap *t)
{
/* Assuming a cyclic list, and the element is in it. */
if (t->next == t) {
*list = NULL;
} else {
if (*list == t)
*list = t->next;
t->next->prev = t->prev;
t->prev->next = t->next;
}
t->next = t->prev = NULL; /* Safety. */
}
private inline void
band_list_insert_last(gx_san_trap **list, gx_san_trap *t)
{
/* Assuming a cyclic list. */
if (*list == 0) {
*list = t->next = t->prev = t;
} else {
gx_san_trap *last = band_list_last(*list);
gx_san_trap *first = *list;
t->next = first;
t->prev = last;
last->next = first->prev = t;
}
}
private inline void
cont_list_insert_last(gx_san_trap_contact **list, gx_san_trap_contact *t)
{
/* Assuming a cyclic list. */
if (*list == 0) {
*list = t->next = t->prev = t;
} else {
gx_san_trap_contact *last = cont_list_last(*list);
gx_san_trap_contact *first = *list;
t->next = first;
t->prev = last;
last->next = first->prev = t;
}
}
private inline bool
trap_is_last(const gx_san_trap *list, const gx_san_trap *t)
{
/* Assuming a non-empty cyclic list, and the anchor points to the first element. */
return t->next == list;
}
private inline void
check_band_list(const gx_san_trap *list)
{
#if DEBUG
if (list != NULL) {
const gx_san_trap *t = list;
while (t->next != list) {
assert(t->xrtop <= t->next->xltop);
t = t->next;
}
}
#endif
}
private void
try_unite_last_trap(gx_device_spot_analyzer *padev, fixed xlbot)
{
if (padev->bot_band != NULL && padev->top_band != NULL) {
gx_san_trap *last = band_list_last(padev->top_band);
/* If the last trapeziod is a prolongation of its bottom contact,
unite it and release the last trapezoid and the last contact. */
if (last->lower != NULL && last->xrbot < xlbot &&
(last->prev == last || last->prev->xrbot < last->xlbot)) {
gx_san_trap *t = last->lower->lower;
if (last->lower->next == last->lower &&
t->l == last->l && t->r == last->r) {
if (padev->bot_current == t)
padev->bot_current = (t == band_list_last(padev->bot_band) ? NULL : t->next);
band_list_remove(&padev->top_band, last);
band_list_remove(&padev->bot_band, t);
check_band_list(padev->bot_band);
band_list_insert_last(&padev->top_band, t);
t->ytop = last->ytop;
t->xltop = last->xltop;
t->xrtop = last->xrtop;
vd_quad(t->xlbot, t->ybot, t->xrbot, t->ybot,
t->xrtop, t->ytop, t->xltop, t->ytop, 1, VD_TRAP_U_COLOR);
trap_unreserve(padev, last);
cont_unreserve(padev, last->lower);
check_band_list(padev->top_band);
check_band_list(padev->bot_band);
}
}
}
}
/* --------------------- Accessories ------------------------- */
/* Obtain a spot analyzer device. */
int
gx_san__obtain(gs_memory_t *mem, gx_device_spot_analyzer **ppadev)
{
gx_device_spot_analyzer *padev;
int code;
if (*ppadev != 0) {
(*ppadev)->lock++;
return 0;
}
padev = gs_alloc_struct(mem, gx_device_spot_analyzer,
&st_device_spot_analyzer, "gx_san__obtain");
if (padev == 0)
return_error(gs_error_VMerror);
gx_device_init((gx_device *)padev, (const gx_device *)&gx_spot_analyzer_device,
mem, false);
code = gs_opendevice((gx_device *)padev);
if (code < 0) {
gs_free_object(mem, padev, "gx_san__obtain");
return code;
}
padev->lock = 1;
*ppadev = padev;
return 0;
}
void
gx_san__release(gx_device_spot_analyzer **ppadev)
{
gx_device_spot_analyzer *padev = *ppadev;
if (padev == NULL) {
eprintf("Extra call to gx_san__release.");
return;
}
if(--padev->lock < 0) {
eprintf("Wrong lock to gx_san__release.");
return;
}
if (padev->lock == 0) {
*ppadev = NULL;
rc_decrement(padev, "gx_san__release");
}
}
/* Start accumulating a path. */
void
gx_san_begin(gx_device_spot_analyzer *padev)
{
padev->bot_band = NULL;
padev->top_band = NULL;
padev->bot_current = NULL;
padev->trap_buffer_count = 0;
padev->cont_buffer_count = 0;
}
/* Store a tarpezoid. */
/* Assumes an Y-band scanning order with increasing X inside a band. */
int
gx_san_trap_store(gx_device_spot_analyzer *padev,
fixed ybot, fixed ytop, fixed xlbot, fixed xrbot, fixed xltop, fixed xrtop,
const segment *r, const segment *l)
{
gx_san_trap *last;
if (padev->top_band != NULL && padev->top_band->ytop != ytop) {
try_unite_last_trap(padev, max_int);
/* Step to a new band. */
padev->bot_band = padev->bot_current = padev->top_band;
padev->top_band = NULL;
}
if (padev->bot_band != NULL && padev->bot_band->ytop != ybot) {
/* The Y-projection of the spot is not contiguous. */
padev->top_band = NULL;
}
if (padev->top_band != NULL)
try_unite_last_trap(padev, xlbot);
check_band_list(padev->bot_band);
check_band_list(padev->top_band);
/* Make new trapeziod. */
last = trap_reserve(padev);
if (last == NULL)
return_error(gs_error_VMerror);
last->ybot = ybot;
last->ytop = ytop;
last->xlbot = xlbot;
last->xrbot = xrbot;
last->xltop = xltop;
last->xrtop = xrtop;
last->l = l;
last->r = r;
last->lower = 0;
vd_quad(last->xlbot, last->ybot, last->xrbot, last->ybot,
last->xrtop, last->ytop, last->xltop, last->ytop, 1, VD_TRAP_N_COLOR);
band_list_insert_last(&padev->top_band, last);
check_band_list(padev->top_band);
while (padev->bot_current != NULL && padev->bot_current->xrtop < xlbot)
padev->bot_current = (trap_is_last(padev->bot_band, padev->bot_current)
? NULL : padev->bot_current->next);
if (padev->bot_current != 0) {
gx_san_trap *t = padev->bot_current;
gx_san_trap *bot_last = band_list_last(padev->bot_band);
while(t->xltop <= xrbot) {
gx_san_trap_contact *cont = cont_reserve(padev);
if (cont == NULL)
return_error(gs_error_VMerror);
cont->lower = t;
cont->upper = last;
vd_bar((t->xltop + t->xrtop + t->xlbot + t->xrbot) / 4, (t->ytop + t->ybot) / 2,
(last->xltop + last->xrtop + last->xlbot + last->xrbot) / 4,
(last->ytop + last->ybot) / 2, 0, VD_CONT_COLOR);
cont_list_insert_last(&last->lower, cont);
if (t == bot_last)
break;
t = t->next;
}
}
return 0;
}
/* Finish accumulating a path. */
void
gx_san_end(const gx_device_spot_analyzer *padev)
{
}
/* Generate stems. */
int
gx_san_generate_stems(gx_device_spot_analyzer *padev,
void *client_data,
int (*handler)(void *client_data, gx_san_sect *ss))
{
return 0;
}
--- NEW FILE: gzspotan.h ---
/* Copyright (C) 2003 Aladdin Enterprises. All rights reserved.
This software is provided AS-IS with no warranty, either express or
implied.
This software is distributed under license and may not be copied,
modified or distributed except as expressly authorized under the terms
of the license contained in the file LICENSE in this distribution.
For more information about licensing, please refer to
http://www.ghostscript.com/licensing/. For information on
commercial licensing, go to http://www.artifex.com/licensing/ or
contact Artifex Software, Inc., 101 Lucas Valley Road #110,
San Rafael, CA 94903, U.S.A., +1(415)492-9861.
*/
/* $Id: gzspotan.h,v 1.1 2003/11/17 16:42:48 igor Exp $ */
/* State and interface definitions for a spot analyzer device. */
/*
* A spot analyzer device performs an analyzis while handling an output
* of the trapezoid fill algorithm for 2 purposes :
* a glyph grid fitting, and
* a glyph antialiased rendering any number of alpha bits.
* Currently we only implement a vertical stem recognition for the grid fitting.
*/
#ifndef gzspotan_INCLUDED
# define gzspotan_INCLUDED
#include "gxdevcli.h"
#ifndef segment_DEFINED
# define segment_DEFINED
typedef struct segment_s segment; /* gzpath.h */
#endif
#ifndef gx_device_spot_analyzer_DEFINED
# define gx_device_spot_analyzer_DEFINED
typedef struct gx_device_spot_analyzer_s gx_device_spot_analyzer;
#endif
/* -------------- Structures ----------------------------- */
typedef struct gx_san_trap_s gx_san_trap;
typedef struct gx_san_trap_contact_s gx_san_trap_contact;
/* A trapezoid. */
struct gx_san_trap_s {
/* The geometry : */
fixed ybot, ytop;
fixed xlbot, xrbot, xltop, xrtop;
/* The spot topology representation : */
gx_san_trap_contact *lower; /* Neighbours of the upper band. */
const segment *l; /* Outline pointer : left boundary. */
const segment *r; /* Outline pointer : right boundary. */
/* The topology reconstrustor work data : */
gx_san_trap *next; /* Next with same ytop. */
gx_san_trap *prev; /* Prev with same ytop. */
/* The stem recognizer work data : */
};
#define private_st_san_trap() /* No GC invocations */\
gs_private_st_simple(st_san_trap, gx_san_trap, "gx_san_trap")
/* A contact of 2 trapezoids. */
/* Represents a neighbourship through a band boundary. */
struct gx_san_trap_contact_s {
gx_san_trap_contact *next; /* Next element of the same relation, a cyclic list. */
gx_san_trap_contact *prev; /* Prev element of the same relation, a cyclic list. */
gx_san_trap *upper, *lower; /* A contacting pair. */
};
#define private_st_san_trap_contact() /* No GC invocations */\
gs_private_st_simple(st_san_trap_contact, gx_san_trap_contact, "gx_san_trap")
/* A stem section. */
typedef struct gx_san_sect_s gx_san_sect;
struct gx_san_sect_s {
fixed y, xl, xr;
const segment *l, *r;
};
/* A spot analyzer device. */
struct gx_device_spot_analyzer_s {
gx_device_common;
int lock;
gx_san_trap *trap_buffer;
gx_san_trap_contact *cont_buffer;
int trap_buffer_count, trap_buffer_max;
int cont_buffer_count, cont_buffer_max;
/* The topology reconstrustor work data (no GC invocations) : */
gx_san_trap *bot_band;
gx_san_trap *top_band;
gx_san_trap *bot_current;
/* The stem recognizer work data (no GC invocations) : */
};
extern_st(st_device_spot_analyzer);
#define public_st_device_spot_analyzer()\
gs_public_st_suffix_add2_final(st_device_spot_analyzer, gx_device_spot_analyzer,\
"gx_device_spot_analyzer", device_spot_analyzer_enum_ptrs,\
device_spot_analyzer_reloc_ptrs, gx_device_finalize, st_device,\
trap_buffer, cont_buffer)
/* -------------- Interface methods ----------------------------- */
/* Obtain a spot analyzer device. */
int gx_san__obtain(gs_memory_t *mem, gx_device_spot_analyzer **ppadev);
/* Obtain a spot analyzer device. */
void gx_san__release(gx_device_spot_analyzer **ppadev);
/* Start accumulating a path. */
void gx_san_begin(gx_device_spot_analyzer *padev);
/* Store a tarpezoid. */
/* Assumes an Y-band scanning order with increasing X inside a band. */
int gx_san_trap_store(gx_device_spot_analyzer *padev,
fixed ybot, fixed ytop, fixed xlbot, fixed xrbot, fixed xltop, fixed xrtop,
const segment *r, const segment *l);
/* Finish accumulating a path. */
void gx_san_end(const gx_device_spot_analyzer *padev);
/* Generate stems. */
int gx_san_generate_stems(gx_device_spot_analyzer *padev,
void *client_data,
int (*handler)(void *client_data, gx_san_sect *ss));
#endif /* gzspotan_INCLUDED */
Index: gsfont.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gsfont.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- gsfont.c 9 Oct 2003 20:29:12 -0000 1.25
+++ gsfont.c 17 Nov 2003 16:42:48 -0000 1.26
@@ -266,6 +266,9 @@
pdir->grid_fit_tt = false;
pdir->memory = struct_mem;
pdir->tti = 0;
+#if TT_GRID_FITTING
+ pdir->san = 0;
+#endif
#endif
return pdir;
}
Index: gxfill.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gxfill.c,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -d -r1.49 -r1.50
--- gxfill.c 30 Oct 2003 12:56:12 -0000 1.49
+++ gxfill.c 17 Nov 2003 16:42:48 -0000 1.50
@@ -32,6 +32,9 @@
#include "gxfill.h"
#include "gsptype2.h"
#include "gdevddrw.h"
+#if TT_GRID_FITTING
+# include "gzspotan.h" /* Only for gx_san_trap_store. */
+#endif
#include "vdtrace.h"
/*
@@ -41,7 +44,7 @@
*/
#define FILL_SCAN_LINES
-#define FILL_TRAPEZOIDS
+#define FILL_TRAPEZOIDS /* Necessary for TT_GRID_FITTING. */
/*
* Define whether to sample curves when using the scan line algorithm
* rather than flattening them. This produces more accurate output, at
@@ -263,6 +266,11 @@
lst.bbox_left = fixed2int(ibox.p.x - adjust.x - fixed_epsilon);
lst.bbox_width = fixed2int(fixed_ceiling(ibox.q.x + adjust.x)) - lst.bbox_left;
pseudo_rasterization = ((adjust.x | adjust.y) == 0 &&
+# if TT_GRID_FITTING
+ gs_object_type(dev->memory, dev) != &st_device_spot_analyzer &&
+# else
+ 1 &&
+# endif
ibox.q.y - ibox.p.y < SMALL_CHARACTER * fixed_scale &&
ibox.q.x - ibox.p.x < SMALL_CHARACTER * fixed_scale);
if (params->fill_zero_width && !pseudo_rasterization)
@@ -373,6 +381,10 @@
#else
fill_by_trapezoids = true;
#endif
+#if TT_GRID_FITTING
+ if (gs_object_type(dev->memory, dev) == &st_device_spot_analyzer)
+ fill_by_trapezoids = true;
+#endif
#ifdef FILL_TRAPEZOIDS
if (fill_by_trapezoids && !DOUBLE_WRITE_OK()) {
/* Avoid filling rectangles by scan line. */
@@ -1218,6 +1230,15 @@
*/
int code;
+#if TT_GRID_FITTING
+ /* We can't pass data through the device interface because
+ we need to pass segment pointers. We're unhappy of that. */
+ if (gs_object_type(dev->memory, dev) == &st_device_spot_analyzer) {
+ return gx_san_trap_store((gx_device_spot_analyzer *)dev,
+ y, y1, xlbot, xbot, xltop, xtop, flp->pseg, alp->pseg);
+ }
+#endif
+
if (xltop == xlbot && xtop == xbot) {
int yi = fixed2int_pixround(y - adjust_below);
int wi = fixed2int_pixround(y1 + adjust_above) - yi;
@@ -1390,6 +1411,9 @@
int code;
bool fill_direct = color_writes_pure(pdevc, lop);
const bool pseudo_rasterization = ll->pseudo_rasterization;
+#if TT_GRID_FITTING
+ const bool all_bands = (gs_object_type(dev->memory, dev) == &st_device_spot_analyzer);
+#endif
dev_proc_fill_rectangle((*fill_rect));
@@ -1492,7 +1516,11 @@
}
/* Fill a multi-trapezoid band for the active lines. */
covering_pixel_centers = COVERING_PIXEL_CENTERS(y, y1, adjust_below, adjust_above);
- if (covering_pixel_centers) {
+ if (covering_pixel_centers
+# if TT_GRID_FITTING
+ || all_bands
+# endif
+ ) {
fixed xlbot, xltop; /* as of last "outside" line */
int inside = 0;
active_line *flp;
Index: gxttfb.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gxttfb.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- gxttfb.c 21 Oct 2003 01:43:28 -0000 1.17
+++ gxttfb.c 17 Nov 2003 16:42:48 -0000 1.18
@@ -31,6 +31,11 @@
#include "gdebug.h"
#include "memory_.h"
#include "math_.h"
+#if TT_GRID_FITTING
+# include "gxistate.h"
+# include "gxpaint.h"
+# include "gzspotan.h"
+#endif
#include <stdarg.h>
gs_public_st_composite(st_gx_ttfReader, gx_ttfReader,
@@ -333,6 +338,10 @@
m->memory = mem;
if(ttfInterpreter__obtain(&m->super, &dir->tti))
return 0;
+#if TT_GRID_FITTING
+ if(gx_san__obtain(mem, &dir->san))
+ return 0;
+#endif
ttf = gs_alloc_struct(mem, ttfFont, &st_ttfFont, "ttfFont__create");
if (ttf == NULL)
return 0;
@@ -351,6 +360,9 @@
ttfFont__finit(this);
mem->free(mem, this, "ttfFont__destroy");
ttfInterpreter__release(&dir->tti);
+#if TT_GRID_FITTING
+ gx_san__release(&dir->san);
+#endif
#endif
}
@@ -456,6 +468,30 @@
/*----------------------------------------------*/
+#if TT_GRID_FITTING
+private int grid_fit(gx_device_spot_analyzer *padev,
+ gx_path *path, const gs_log2_scale_point *pscale)
+{
+ /* Not completed yet. */
+ gs_imager_state is_stub;
+ gx_fill_params params;
+ gx_device_color devc_stub;
+ int code;
+
+ memset(&is_stub, 0, sizeof(is_stub));
+ set_nonclient_dev_color(&devc_stub, 1);
+ params.rule = gx_rule_winding_number;
+ params.adjust.x = params.adjust.y = 0;
+ params.flatness = (float)0.2;
+ params.fill_zero_width = false;
+ gx_san_begin(padev);
+ code = dev_proc(padev, fill_path)((gx_device *)padev,
+ &is_stub, path, ¶ms, &devc_stub, NULL);
+ gx_san_end(padev);
+ return code;
+}
+#endif
+
int gx_ttf_outline(ttfFont *ttf, gx_ttfReader *r, gs_font_type42 *pfont, int glyph_index,
const gs_matrix *m, const gs_log2_scale_point *pscale,
gx_path *path, bool design_grid)
@@ -491,9 +527,12 @@
e.w.y = 0;
gx_ttfReader__Reset(r);
ttfOutliner__init(&o, ttf, &r->super, &e.super, true, false, pfont->WMode != 0);
- switch(ttfOutliner__Outline(&o, glyph_index,
- subpix_origin.x, subpix_origin.y, &m1)) {
+ switch(ttfOutliner__Outline(&o, glyph_index, subpix_origin.x, subpix_origin.y, &m1)) {
case fNoError:
+# if TT_GRID_FITTING
+ if (!gs_currentgridfittt(pfont->dir))
+ return grid_fit(pfont->dir->san, path, pscale);
+# endif
return 0;
case fMemoryError:
return_error(gs_error_VMerror);
@@ -502,6 +541,10 @@
case fPatented:
/* The returned outline did not apply a bytecode (it is not grid-fitted). */
WarnPatented(pfont, ttf, "Some glyphs of the font");
+# if TT_GRID_FITTING
+ if (!gs_currentgridfittt(pfont->dir))
+ return grid_fit(pfont->dir->san, path, pscale);
+# endif
return 0;
default:
{ int code = r->super.Error(&r->super);
Index: gx.h
===================================================================
RCS file: /cvs/ghostscript/gs/src/gx.h,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- gx.h 28 Oct 2003 14:42:40 -0000 1.14
+++ gx.h 17 Nov 2003 16:42:48 -0000 1.15
@@ -28,6 +28,7 @@
#include "gdebug.h"
#define NEW_TT_INTERPRETER 1
+#define TT_GRID_FITTING (NEW_TT_INTERPRETER && 0) /* old code = 0, new code = 1. */
/* Define opaque types for the graphics state. */
/* This is used so pervasively that we define it here, */
Index: gxfcache.h
===================================================================
RCS file: /cvs/ghostscript/gs/src/gxfcache.h,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- gxfcache.h 10 Oct 2003 07:08:22 -0000 1.20
+++ gxfcache.h 17 Nov 2003 16:42:48 -0000 1.21
@@ -42,6 +42,8 @@
# define gs_matrix_DEFINED
typedef struct gs_matrix_s gs_matrix;
#endif
+
+#if NEW_TT_INTERPRETER
#ifndef ttfFont_DEFINED
# define ttfFont_DEFINED
typedef struct ttfFont_s ttfFont;
@@ -55,6 +57,15 @@
typedef struct ttfInterpreter_s ttfInterpreter;
#endif
+#if TT_GRID_FITTING
+#ifndef gx_device_spot_analyzer_DEFINED
+# define gx_device_spot_analyzer_DEFINED
+typedef struct gx_device_spot_analyzer_s gx_device_spot_analyzer;
+#endif
+#endif /* TT_GRID_FITTING */
+#endif /* NEW_TT_INTERPRETER */
+
+
/*
* Define the entry for a cached (font,matrix) pair. If the UID
* is valid, the font pointer may be 0, since we keep entries even for
@@ -289,6 +300,9 @@
ttfInterpreter *tti;
/* User parameter GridFitTT. */
bool grid_fit_tt;
+#if TT_GRID_FITTING
+ gx_device_spot_analyzer *san;
+#endif
#endif
};
@@ -298,18 +312,26 @@
/* Enumerate the pointers in a font directory, except for orig_fonts. */
#if NEW_TT_INTERPRETER
+#if TT_GRID_FITTING
+#define font_dir_do_ptrs(m)\
+ /*m(-,orig_fonts)*/ m(0,scaled_fonts) m(1,fmcache.mdata)\
+ m(2,ccache.table) m(3,ccache.mark_glyph_data)\
+ m(4,glyph_to_unicode_table) m(5,tti) m(6,san)
+#define st_font_dir_max_ptrs 7
+#else
#define font_dir_do_ptrs(m)\
/*m(-,orig_fonts)*/ m(0,scaled_fonts) m(1,fmcache.mdata)\
m(2,ccache.table) m(3,ccache.mark_glyph_data)\
m(4,glyph_to_unicode_table) m(5,tti)
#define st_font_dir_max_ptrs 6
+#endif /* TT_GRID_FITTING */
#else
#define font_dir_do_ptrs(m)\
/*m(-,orig_fonts)*/ m(0,scaled_fonts) m(1,fmcache.mdata)\
m(2,ccache.table) m(3,ccache.mark_glyph_data)\
m(4,glyph_to_unicode_table)
#define st_font_dir_max_ptrs 5
-#endif
+#endif /* NEW_TT_INTERPRETER */
/* Character cache procedures (in gxccache.c and gxccman.c) */
int gx_char_cache_alloc(gs_memory_t * struct_mem, gs_memory_t * bits_mem,
Index: gxfdrop.h
===================================================================
RCS file: /cvs/ghostscript/gs/src/gxfdrop.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- gxfdrop.h 30 Oct 2003 09:33:33 -0000 1.1
+++ gxfdrop.h 17 Nov 2003 16:42:48 -0000 1.2
@@ -105,7 +105,7 @@
extern_st(st_section);
/* vd_trace helpers. */
-#define VD_SCALE 0.004
+#define VD_SCALE 0.04
#define VD_RECT(x, y, w, h, c) vd_rect(int2fixed(x), int2fixed(y), int2fixed(x + w), int2fixed(y + h), 1, c)
#define VD_TRAP_COLOR RGB(0, 255, 255)
#define VD_MARG_COLOR RGB(255, 0, 0)
Index: lib.mak
===================================================================
RCS file: /cvs/ghostscript/gs/src/lib.mak,v
retrieving revision 1.147
retrieving revision 1.148
diff -u -d -r1.147 -r1.148
--- lib.mak 14 Nov 2003 18:59:56 -0000 1.147
+++ lib.mak 17 Nov 2003 16:42:48 -0000 1.148
@@ -496,6 +496,7 @@
ttfoutl_h=$(GLSRC)ttfoutl.h
gxttfb_h = $(GLSRC)gxttfb.h $(ttfoutl_h)
+gzspotan_h = $(GLSRC)gzspotan.h $(gxdevcli_h)
### Executable code
@@ -592,7 +593,7 @@
$(gsstruct_h)\
$(gxdcolor_h) $(gxdevice_h) $(gxfixed_h) $(gxhttile_h)\
$(gxistate_h) $(gxpaint_h) $(gxfill_h) $(gxfdrop_h) $(gsptype2_h)\
- $(gzcpath_h) $(gzpath_h) $(gdevddrw_h) $(vdtrace_h)
+ $(gzcpath_h) $(gzpath_h) $(gzspotan_h) $(gdevddrw_h) $(vdtrace_h)
$(GLCC) $(GLO_)gxfill.$(OBJ) $(C_) $(GLSRC)gxfill.c
$(GLOBJ)gxfdrop.$(OBJ) : $(GLSRC)gxfdrop.c $(GXERR)\
@@ -1785,7 +1786,7 @@
ttflib_=$(GLOBJ)gstype42.$(OBJ) $(GLOBJ)gxchrout.$(OBJ) \
$(GLOBJ)ttcalc.$(OBJ) $(GLOBJ)ttfinp.$(OBJ) $(GLOBJ)ttfmain.$(OBJ) $(GLOBJ)ttfmemd.$(OBJ) \
$(GLOBJ)ttinterp.$(OBJ) $(GLOBJ)ttload.$(OBJ) $(GLOBJ)ttobjs.$(OBJ) \
- $(GLOBJ)gxttfb.$(OBJ)
+ $(GLOBJ)gxttfb.$(OBJ) $(GLOBJ)gzspotan.$(OBJ)
$(GLD)ttflib.dev : $(LIB_MAK) $(ECHOGS_XE) $(ttflib_)
$(SETMOD) $(GLD)ttflib $(ttflib_)
@@ -1843,9 +1844,16 @@
$(GLOBJ)gxttfb.$(OBJ) : $(GLSRC)gxttfb.c $(GXERR) \
$(gx_h) $(gxfont_h) $(gxfont42_h) $(gxttfb_h) $(gxfcache_h) $(ttfmemd_h)\
- $(gsstruct_h) $(gserrors_h) $(gsfont_h) $(gsdebug_h) $(memory__h) $(math__h)
+ $(gsstruct_h) $(gserrors_h) $(gsfont_h) $(gsdebug_h) $(memory__h) $(math__h)\
+ $(gxistate_h) $(gxpaint_h) $(gzspotan_h)
$(GLCC) $(GLO_)gxttfb.$(OBJ) $(C_) $(GLSRC)gxttfb.c
+$(GLOBJ)gzspotan.$(OBJ) : $(GLSRC)gzspotan.c $(GXERR)\
+ $(gx_h) $(gserrors_h) $(gsdevice_h) $(gsfixed_h) $(gxdevice_h)\
+ $(gzspotan_h) $(memory__h) $(vdtrace_h)
+ $(GLCC) $(GLO_)gzspotan.$(OBJ) $(C_) $(GLSRC)gzspotan.c
+
+
# -------- Composite (PostScript Type 0) font support -------- #
gxcid_h=$(GLSRC)gxcid.h $(gsstype_h)
More information about the gs-cvs
mailing list