Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F631124
pshrec.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Authored By
Unknown
Size
31 KB
Referenced Files
None
Subscribers
None
pshrec.c
View Options
/***************************************************************************/
/* */
/* pshrec.c */
/* */
/* FreeType PostScript hints recorder (body). */
/* */
/* Copyright 2001, 2002, 2003, 2004, 2007, 2009 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
#include
<ft2build.h>
#include FT_FREETYPE_H
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_CALC_H
#include
"pshrec.h"
#include
"pshalgo.h"
#include
"pshnterr.h"
#undef FT_COMPONENT
#define FT_COMPONENT trace_pshrec
#ifdef DEBUG_HINTER
PS_Hints
ps_debug_hints
=
0
;
int
ps_debug_no_horz_hints
=
0
;
int
ps_debug_no_vert_hints
=
0
;
#endif
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** PS_HINT MANAGEMENT *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* destroy hints table */
static
void
ps_hint_table_done
(
PS_Hint_Table
table
,
FT_Memory
memory
)
{
FT_FREE
(
table
->
hints
);
table
->
num_hints
=
0
;
table
->
max_hints
=
0
;
}
/* ensure that a table can contain "count" elements */
static
FT_Error
ps_hint_table_ensure
(
PS_Hint_Table
table
,
FT_UInt
count
,
FT_Memory
memory
)
{
FT_UInt
old_max
=
table
->
max_hints
;
FT_UInt
new_max
=
count
;
FT_Error
error
=
PSH_Err_Ok
;
if
(
new_max
>
old_max
)
{
/* try to grow the table */
new_max
=
FT_PAD_CEIL
(
new_max
,
8
);
if
(
!
FT_RENEW_ARRAY
(
table
->
hints
,
old_max
,
new_max
)
)
table
->
max_hints
=
new_max
;
}
return
error
;
}
static
FT_Error
ps_hint_table_alloc
(
PS_Hint_Table
table
,
FT_Memory
memory
,
PS_Hint
*
ahint
)
{
FT_Error
error
=
PSH_Err_Ok
;
FT_UInt
count
;
PS_Hint
hint
=
0
;
count
=
table
->
num_hints
;
count
++
;
if
(
count
>=
table
->
max_hints
)
{
error
=
ps_hint_table_ensure
(
table
,
count
,
memory
);
if
(
error
)
goto
Exit
;
}
hint
=
table
->
hints
+
count
-
1
;
hint
->
pos
=
0
;
hint
->
len
=
0
;
hint
->
flags
=
0
;
table
->
num_hints
=
count
;
Exit
:
*
ahint
=
hint
;
return
error
;
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** PS_MASK MANAGEMENT *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* destroy mask */
static
void
ps_mask_done
(
PS_Mask
mask
,
FT_Memory
memory
)
{
FT_FREE
(
mask
->
bytes
);
mask
->
num_bits
=
0
;
mask
->
max_bits
=
0
;
mask
->
end_point
=
0
;
}
/* ensure that a mask can contain "count" bits */
static
FT_Error
ps_mask_ensure
(
PS_Mask
mask
,
FT_UInt
count
,
FT_Memory
memory
)
{
FT_UInt
old_max
=
(
mask
->
max_bits
+
7
)
>>
3
;
FT_UInt
new_max
=
(
count
+
7
)
>>
3
;
FT_Error
error
=
PSH_Err_Ok
;
if
(
new_max
>
old_max
)
{
new_max
=
FT_PAD_CEIL
(
new_max
,
8
);
if
(
!
FT_RENEW_ARRAY
(
mask
->
bytes
,
old_max
,
new_max
)
)
mask
->
max_bits
=
new_max
*
8
;
}
return
error
;
}
/* test a bit value in a given mask */
static
FT_Int
ps_mask_test_bit
(
PS_Mask
mask
,
FT_Int
idx
)
{
if
(
(
FT_UInt
)
idx
>=
mask
->
num_bits
)
return
0
;
return
mask
->
bytes
[
idx
>>
3
]
&
(
0x80
>>
(
idx
&
7
)
);
}
/* clear a given bit */
static
void
ps_mask_clear_bit
(
PS_Mask
mask
,
FT_Int
idx
)
{
FT_Byte
*
p
;
if
(
(
FT_UInt
)
idx
>=
mask
->
num_bits
)
return
;
p
=
mask
->
bytes
+
(
idx
>>
3
);
p
[
0
]
=
(
FT_Byte
)(
p
[
0
]
&
~
(
0x80
>>
(
idx
&
7
)
)
);
}
/* set a given bit, possibly grow the mask */
static
FT_Error
ps_mask_set_bit
(
PS_Mask
mask
,
FT_Int
idx
,
FT_Memory
memory
)
{
FT_Error
error
=
PSH_Err_Ok
;
FT_Byte
*
p
;
if
(
idx
<
0
)
goto
Exit
;
if
(
(
FT_UInt
)
idx
>=
mask
->
num_bits
)
{
error
=
ps_mask_ensure
(
mask
,
idx
+
1
,
memory
);
if
(
error
)
goto
Exit
;
mask
->
num_bits
=
idx
+
1
;
}
p
=
mask
->
bytes
+
(
idx
>>
3
);
p
[
0
]
=
(
FT_Byte
)(
p
[
0
]
|
(
0x80
>>
(
idx
&
7
)
)
);
Exit
:
return
error
;
}
/* destroy mask table */
static
void
ps_mask_table_done
(
PS_Mask_Table
table
,
FT_Memory
memory
)
{
FT_UInt
count
=
table
->
max_masks
;
PS_Mask
mask
=
table
->
masks
;
for
(
;
count
>
0
;
count
--
,
mask
++
)
ps_mask_done
(
mask
,
memory
);
FT_FREE
(
table
->
masks
);
table
->
num_masks
=
0
;
table
->
max_masks
=
0
;
}
/* ensure that a mask table can contain "count" masks */
static
FT_Error
ps_mask_table_ensure
(
PS_Mask_Table
table
,
FT_UInt
count
,
FT_Memory
memory
)
{
FT_UInt
old_max
=
table
->
max_masks
;
FT_UInt
new_max
=
count
;
FT_Error
error
=
PSH_Err_Ok
;
if
(
new_max
>
old_max
)
{
new_max
=
FT_PAD_CEIL
(
new_max
,
8
);
if
(
!
FT_RENEW_ARRAY
(
table
->
masks
,
old_max
,
new_max
)
)
table
->
max_masks
=
new_max
;
}
return
error
;
}
/* allocate a new mask in a table */
static
FT_Error
ps_mask_table_alloc
(
PS_Mask_Table
table
,
FT_Memory
memory
,
PS_Mask
*
amask
)
{
FT_UInt
count
;
FT_Error
error
=
PSH_Err_Ok
;
PS_Mask
mask
=
0
;
count
=
table
->
num_masks
;
count
++
;
if
(
count
>
table
->
max_masks
)
{
error
=
ps_mask_table_ensure
(
table
,
count
,
memory
);
if
(
error
)
goto
Exit
;
}
mask
=
table
->
masks
+
count
-
1
;
mask
->
num_bits
=
0
;
mask
->
end_point
=
0
;
table
->
num_masks
=
count
;
Exit
:
*
amask
=
mask
;
return
error
;
}
/* return last hint mask in a table, create one if the table is empty */
static
FT_Error
ps_mask_table_last
(
PS_Mask_Table
table
,
FT_Memory
memory
,
PS_Mask
*
amask
)
{
FT_Error
error
=
PSH_Err_Ok
;
FT_UInt
count
;
PS_Mask
mask
;
count
=
table
->
num_masks
;
if
(
count
==
0
)
{
error
=
ps_mask_table_alloc
(
table
,
memory
,
&
mask
);
if
(
error
)
goto
Exit
;
}
else
mask
=
table
->
masks
+
count
-
1
;
Exit
:
*
amask
=
mask
;
return
error
;
}
/* set a new mask to a given bit range */
static
FT_Error
ps_mask_table_set_bits
(
PS_Mask_Table
table
,
const
FT_Byte
*
source
,
FT_UInt
bit_pos
,
FT_UInt
bit_count
,
FT_Memory
memory
)
{
FT_Error
error
=
PSH_Err_Ok
;
PS_Mask
mask
;
error
=
ps_mask_table_last
(
table
,
memory
,
&
mask
);
if
(
error
)
goto
Exit
;
error
=
ps_mask_ensure
(
mask
,
bit_count
,
memory
);
if
(
error
)
goto
Exit
;
mask
->
num_bits
=
bit_count
;
/* now, copy bits */
{
FT_Byte
*
read
=
(
FT_Byte
*
)
source
+
(
bit_pos
>>
3
);
FT_Int
rmask
=
0x80
>>
(
bit_pos
&
7
);
FT_Byte
*
write
=
mask
->
bytes
;
FT_Int
wmask
=
0x80
;
FT_Int
val
;
for
(
;
bit_count
>
0
;
bit_count
--
)
{
val
=
write
[
0
]
&
~
wmask
;
if
(
read
[
0
]
&
rmask
)
val
|=
wmask
;
write
[
0
]
=
(
FT_Byte
)
val
;
rmask
>>=
1
;
if
(
rmask
==
0
)
{
read
++
;
rmask
=
0x80
;
}
wmask
>>=
1
;
if
(
wmask
==
0
)
{
write
++
;
wmask
=
0x80
;
}
}
}
Exit
:
return
error
;
}
/* test whether two masks in a table intersect */
static
FT_Int
ps_mask_table_test_intersect
(
PS_Mask_Table
table
,
FT_Int
index1
,
FT_Int
index2
)
{
PS_Mask
mask1
=
table
->
masks
+
index1
;
PS_Mask
mask2
=
table
->
masks
+
index2
;
FT_Byte
*
p1
=
mask1
->
bytes
;
FT_Byte
*
p2
=
mask2
->
bytes
;
FT_UInt
count1
=
mask1
->
num_bits
;
FT_UInt
count2
=
mask2
->
num_bits
;
FT_UInt
count
;
count
=
(
count1
<=
count2
)
?
count1
:
count2
;
for
(
;
count
>=
8
;
count
-=
8
)
{
if
(
p1
[
0
]
&
p2
[
0
]
)
return
1
;
p1
++
;
p2
++
;
}
if
(
count
==
0
)
return
0
;
return
(
p1
[
0
]
&
p2
[
0
]
)
&
~
(
0xFF
>>
count
);
}
/* merge two masks, used by ps_mask_table_merge_all */
static
FT_Error
ps_mask_table_merge
(
PS_Mask_Table
table
,
FT_Int
index1
,
FT_Int
index2
,
FT_Memory
memory
)
{
FT_UInt
temp
;
FT_Error
error
=
PSH_Err_Ok
;
/* swap index1 and index2 so that index1 < index2 */
if
(
index1
>
index2
)
{
temp
=
index1
;
index1
=
index2
;
index2
=
temp
;
}
if
(
index1
<
index2
&&
index1
>=
0
&&
index2
<
(
FT_Int
)
table
->
num_masks
)
{
/* we need to merge the bitsets of index1 and index2 with a */
/* simple union */
PS_Mask
mask1
=
table
->
masks
+
index1
;
PS_Mask
mask2
=
table
->
masks
+
index2
;
FT_UInt
count1
=
mask1
->
num_bits
;
FT_UInt
count2
=
mask2
->
num_bits
;
FT_Int
delta
;
if
(
count2
>
0
)
{
FT_UInt
pos
;
FT_Byte
*
read
;
FT_Byte
*
write
;
/* if "count2" is greater than "count1", we need to grow the */
/* first bitset, and clear the highest bits */
if
(
count2
>
count1
)
{
error
=
ps_mask_ensure
(
mask1
,
count2
,
memory
);
if
(
error
)
goto
Exit
;
for
(
pos
=
count1
;
pos
<
count2
;
pos
++
)
ps_mask_clear_bit
(
mask1
,
pos
);
}
/* merge (unite) the bitsets */
read
=
mask2
->
bytes
;
write
=
mask1
->
bytes
;
pos
=
(
FT_UInt
)(
(
count2
+
7
)
>>
3
);
for
(
;
pos
>
0
;
pos
--
)
{
write
[
0
]
=
(
FT_Byte
)(
write
[
0
]
|
read
[
0
]
);
write
++
;
read
++
;
}
}
/* Now, remove "mask2" from the list. We need to keep the masks */
/* sorted in order of importance, so move table elements. */
mask2
->
num_bits
=
0
;
mask2
->
end_point
=
0
;
delta
=
table
->
num_masks
-
1
-
index2
;
/* number of masks to move */
if
(
delta
>
0
)
{
/* move to end of table for reuse */
PS_MaskRec
dummy
=
*
mask2
;
ft_memmove
(
mask2
,
mask2
+
1
,
delta
*
sizeof
(
PS_MaskRec
)
);
mask2
[
delta
]
=
dummy
;
}
table
->
num_masks
--
;
}
else
FT_TRACE0
((
"ps_mask_table_merge: ignoring invalid indices (%d,%d)
\n
"
,
index1
,
index2
));
Exit
:
return
error
;
}
/* Try to merge all masks in a given table. This is used to merge */
/* all counter masks into independent counter "paths". */
/* */
static
FT_Error
ps_mask_table_merge_all
(
PS_Mask_Table
table
,
FT_Memory
memory
)
{
FT_Int
index1
,
index2
;
FT_Error
error
=
PSH_Err_Ok
;
for
(
index1
=
table
->
num_masks
-
1
;
index1
>
0
;
index1
--
)
{
for
(
index2
=
index1
-
1
;
index2
>=
0
;
index2
--
)
{
if
(
ps_mask_table_test_intersect
(
table
,
index1
,
index2
)
)
{
error
=
ps_mask_table_merge
(
table
,
index2
,
index1
,
memory
);
if
(
error
)
goto
Exit
;
break
;
}
}
}
Exit
:
return
error
;
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** PS_DIMENSION MANAGEMENT *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* finalize a given dimension */
static
void
ps_dimension_done
(
PS_Dimension
dimension
,
FT_Memory
memory
)
{
ps_mask_table_done
(
&
dimension
->
counters
,
memory
);
ps_mask_table_done
(
&
dimension
->
masks
,
memory
);
ps_hint_table_done
(
&
dimension
->
hints
,
memory
);
}
/* initialize a given dimension */
static
void
ps_dimension_init
(
PS_Dimension
dimension
)
{
dimension
->
hints
.
num_hints
=
0
;
dimension
->
masks
.
num_masks
=
0
;
dimension
->
counters
.
num_masks
=
0
;
}
#if 0
/* set a bit at a given index in the current hint mask */
static FT_Error
ps_dimension_set_mask_bit( PS_Dimension dim,
FT_UInt idx,
FT_Memory memory )
{
PS_Mask mask;
FT_Error error = PSH_Err_Ok;
/* get last hint mask */
error = ps_mask_table_last( &dim->masks, memory, &mask );
if ( error )
goto Exit;
error = ps_mask_set_bit( mask, idx, memory );
Exit:
return error;
}
#endif
/* set the end point in a mask, called from "End" & "Reset" methods */
static
void
ps_dimension_end_mask
(
PS_Dimension
dim
,
FT_UInt
end_point
)
{
FT_UInt
count
=
dim
->
masks
.
num_masks
;
PS_Mask
mask
;
if
(
count
>
0
)
{
mask
=
dim
->
masks
.
masks
+
count
-
1
;
mask
->
end_point
=
end_point
;
}
}
/* set the end point in the current mask, then create a new empty one */
/* (called by "Reset" method) */
static
FT_Error
ps_dimension_reset_mask
(
PS_Dimension
dim
,
FT_UInt
end_point
,
FT_Memory
memory
)
{
PS_Mask
mask
;
/* end current mask */
ps_dimension_end_mask
(
dim
,
end_point
);
/* allocate new one */
return
ps_mask_table_alloc
(
&
dim
->
masks
,
memory
,
&
mask
);
}
/* set a new mask, called from the "T2Stem" method */
static
FT_Error
ps_dimension_set_mask_bits
(
PS_Dimension
dim
,
const
FT_Byte
*
source
,
FT_UInt
source_pos
,
FT_UInt
source_bits
,
FT_UInt
end_point
,
FT_Memory
memory
)
{
FT_Error
error
=
PSH_Err_Ok
;
/* reset current mask, if any */
error
=
ps_dimension_reset_mask
(
dim
,
end_point
,
memory
);
if
(
error
)
goto
Exit
;
/* set bits in new mask */
error
=
ps_mask_table_set_bits
(
&
dim
->
masks
,
source
,
source_pos
,
source_bits
,
memory
);
Exit
:
return
error
;
}
/* add a new single stem (called from "T1Stem" method) */
static
FT_Error
ps_dimension_add_t1stem
(
PS_Dimension
dim
,
FT_Int
pos
,
FT_Int
len
,
FT_Memory
memory
,
FT_Int
*
aindex
)
{
FT_Error
error
=
PSH_Err_Ok
;
FT_UInt
flags
=
0
;
/* detect ghost stem */
if
(
len
<
0
)
{
flags
|=
PS_HINT_FLAG_GHOST
;
if
(
len
==
-21
)
{
flags
|=
PS_HINT_FLAG_BOTTOM
;
pos
+=
len
;
}
len
=
0
;
}
if
(
aindex
)
*
aindex
=
-1
;
/* now, lookup stem in the current hints table */
{
PS_Mask
mask
;
FT_UInt
idx
;
FT_UInt
max
=
dim
->
hints
.
num_hints
;
PS_Hint
hint
=
dim
->
hints
.
hints
;
for
(
idx
=
0
;
idx
<
max
;
idx
++
,
hint
++
)
{
if
(
hint
->
pos
==
pos
&&
hint
->
len
==
len
)
break
;
}
/* we need to create a new hint in the table */
if
(
idx
>=
max
)
{
error
=
ps_hint_table_alloc
(
&
dim
->
hints
,
memory
,
&
hint
);
if
(
error
)
goto
Exit
;
hint
->
pos
=
pos
;
hint
->
len
=
len
;
hint
->
flags
=
flags
;
}
/* now, store the hint in the current mask */
error
=
ps_mask_table_last
(
&
dim
->
masks
,
memory
,
&
mask
);
if
(
error
)
goto
Exit
;
error
=
ps_mask_set_bit
(
mask
,
idx
,
memory
);
if
(
error
)
goto
Exit
;
if
(
aindex
)
*
aindex
=
(
FT_Int
)
idx
;
}
Exit
:
return
error
;
}
/* add a "hstem3/vstem3" counter to our dimension table */
static
FT_Error
ps_dimension_add_counter
(
PS_Dimension
dim
,
FT_Int
hint1
,
FT_Int
hint2
,
FT_Int
hint3
,
FT_Memory
memory
)
{
FT_Error
error
=
PSH_Err_Ok
;
FT_UInt
count
=
dim
->
counters
.
num_masks
;
PS_Mask
counter
=
dim
->
counters
.
masks
;
/* try to find an existing counter mask that already uses */
/* one of these stems here */
for
(
;
count
>
0
;
count
--
,
counter
++
)
{
if
(
ps_mask_test_bit
(
counter
,
hint1
)
||
ps_mask_test_bit
(
counter
,
hint2
)
||
ps_mask_test_bit
(
counter
,
hint3
)
)
break
;
}
/* create a new counter when needed */
if
(
count
==
0
)
{
error
=
ps_mask_table_alloc
(
&
dim
->
counters
,
memory
,
&
counter
);
if
(
error
)
goto
Exit
;
}
/* now, set the bits for our hints in the counter mask */
error
=
ps_mask_set_bit
(
counter
,
hint1
,
memory
);
if
(
error
)
goto
Exit
;
error
=
ps_mask_set_bit
(
counter
,
hint2
,
memory
);
if
(
error
)
goto
Exit
;
error
=
ps_mask_set_bit
(
counter
,
hint3
,
memory
);
if
(
error
)
goto
Exit
;
Exit
:
return
error
;
}
/* end of recording session for a given dimension */
static
FT_Error
ps_dimension_end
(
PS_Dimension
dim
,
FT_UInt
end_point
,
FT_Memory
memory
)
{
/* end hint mask table */
ps_dimension_end_mask
(
dim
,
end_point
);
/* merge all counter masks into independent "paths" */
return
ps_mask_table_merge_all
(
&
dim
->
counters
,
memory
);
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** PS_RECORDER MANAGEMENT *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* destroy hints */
FT_LOCAL
(
void
)
ps_hints_done
(
PS_Hints
hints
)
{
FT_Memory
memory
=
hints
->
memory
;
ps_dimension_done
(
&
hints
->
dimension
[
0
],
memory
);
ps_dimension_done
(
&
hints
->
dimension
[
1
],
memory
);
hints
->
error
=
PSH_Err_Ok
;
hints
->
memory
=
0
;
}
FT_LOCAL
(
FT_Error
)
ps_hints_init
(
PS_Hints
hints
,
FT_Memory
memory
)
{
FT_MEM_ZERO
(
hints
,
sizeof
(
*
hints
)
);
hints
->
memory
=
memory
;
return
PSH_Err_Ok
;
}
/* initialize a hints for a new session */
static
void
ps_hints_open
(
PS_Hints
hints
,
PS_Hint_Type
hint_type
)
{
switch
(
hint_type
)
{
case
PS_HINT_TYPE_1
:
case
PS_HINT_TYPE_2
:
hints
->
error
=
PSH_Err_Ok
;
hints
->
hint_type
=
hint_type
;
ps_dimension_init
(
&
hints
->
dimension
[
0
]
);
ps_dimension_init
(
&
hints
->
dimension
[
1
]
);
break
;
default
:
hints
->
error
=
PSH_Err_Invalid_Argument
;
hints
->
hint_type
=
hint_type
;
FT_TRACE0
((
"ps_hints_open: invalid charstring type
\n
"
));
break
;
}
}
/* add one or more stems to the current hints table */
static
void
ps_hints_stem
(
PS_Hints
hints
,
FT_Int
dimension
,
FT_UInt
count
,
FT_Long
*
stems
)
{
if
(
!
hints
->
error
)
{
/* limit "dimension" to 0..1 */
if
(
dimension
<
0
||
dimension
>
1
)
{
FT_TRACE0
((
"ps_hints_stem: invalid dimension (%d) used
\n
"
,
dimension
));
dimension
=
(
dimension
!=
0
);
}
/* record the stems in the current hints/masks table */
switch
(
hints
->
hint_type
)
{
case
PS_HINT_TYPE_1
:
/* Type 1 "hstem" or "vstem" operator */
case
PS_HINT_TYPE_2
:
/* Type 2 "hstem" or "vstem" operator */
{
PS_Dimension
dim
=
&
hints
->
dimension
[
dimension
];
for
(
;
count
>
0
;
count
--
,
stems
+=
2
)
{
FT_Error
error
;
FT_Memory
memory
=
hints
->
memory
;
error
=
ps_dimension_add_t1stem
(
dim
,
(
FT_Int
)
stems
[
0
],
(
FT_Int
)
stems
[
1
],
memory
,
NULL
);
if
(
error
)
{
FT_ERROR
((
"ps_hints_stem: could not add stem"
" (%d,%d) to hints table
\n
"
,
stems
[
0
],
stems
[
1
]
));
hints
->
error
=
error
;
return
;
}
}
break
;
}
default
:
FT_TRACE0
((
"ps_hints_stem: called with invalid hint type (%d)
\n
"
,
hints
->
hint_type
));
break
;
}
}
}
/* add one Type1 counter stem to the current hints table */
static
void
ps_hints_t1stem3
(
PS_Hints
hints
,
FT_Int
dimension
,
FT_Fixed
*
stems
)
{
FT_Error
error
=
PSH_Err_Ok
;
if
(
!
hints
->
error
)
{
PS_Dimension
dim
;
FT_Memory
memory
=
hints
->
memory
;
FT_Int
count
;
FT_Int
idx
[
3
];
/* limit "dimension" to 0..1 */
if
(
dimension
<
0
||
dimension
>
1
)
{
FT_TRACE0
((
"ps_hints_t1stem3: invalid dimension (%d) used
\n
"
,
dimension
));
dimension
=
(
dimension
!=
0
);
}
dim
=
&
hints
->
dimension
[
dimension
];
/* there must be 6 elements in the 'stem' array */
if
(
hints
->
hint_type
==
PS_HINT_TYPE_1
)
{
/* add the three stems to our hints/masks table */
for
(
count
=
0
;
count
<
3
;
count
++
,
stems
+=
2
)
{
error
=
ps_dimension_add_t1stem
(
dim
,
(
FT_Int
)
FIXED_TO_INT
(
stems
[
0
]
),
(
FT_Int
)
FIXED_TO_INT
(
stems
[
1
]
),
memory
,
&
idx
[
count
]
);
if
(
error
)
goto
Fail
;
}
/* now, add the hints to the counters table */
error
=
ps_dimension_add_counter
(
dim
,
idx
[
0
],
idx
[
1
],
idx
[
2
],
memory
);
if
(
error
)
goto
Fail
;
}
else
{
FT_ERROR
((
"ps_hints_t1stem3: called with invalid hint type
\n
"
));
error
=
PSH_Err_Invalid_Argument
;
goto
Fail
;
}
}
return
;
Fail
:
FT_ERROR
((
"ps_hints_t1stem3: could not add counter stems to table
\n
"
));
hints
->
error
=
error
;
}
/* reset hints (only with Type 1 hints) */
static
void
ps_hints_t1reset
(
PS_Hints
hints
,
FT_UInt
end_point
)
{
FT_Error
error
=
PSH_Err_Ok
;
if
(
!
hints
->
error
)
{
FT_Memory
memory
=
hints
->
memory
;
if
(
hints
->
hint_type
==
PS_HINT_TYPE_1
)
{
error
=
ps_dimension_reset_mask
(
&
hints
->
dimension
[
0
],
end_point
,
memory
);
if
(
error
)
goto
Fail
;
error
=
ps_dimension_reset_mask
(
&
hints
->
dimension
[
1
],
end_point
,
memory
);
if
(
error
)
goto
Fail
;
}
else
{
/* invalid hint type */
error
=
PSH_Err_Invalid_Argument
;
goto
Fail
;
}
}
return
;
Fail
:
hints
->
error
=
error
;
}
/* Type2 "hintmask" operator, add a new hintmask to each direction */
static
void
ps_hints_t2mask
(
PS_Hints
hints
,
FT_UInt
end_point
,
FT_UInt
bit_count
,
const
FT_Byte
*
bytes
)
{
FT_Error
error
;
if
(
!
hints
->
error
)
{
PS_Dimension
dim
=
hints
->
dimension
;
FT_Memory
memory
=
hints
->
memory
;
FT_UInt
count1
=
dim
[
0
].
hints
.
num_hints
;
FT_UInt
count2
=
dim
[
1
].
hints
.
num_hints
;
/* check bit count; must be equal to current total hint count */
if
(
bit_count
!=
count1
+
count2
)
{
FT_TRACE0
((
"ps_hints_t2mask:"
" called with invalid bitcount %d (instead of %d)
\n
"
,
bit_count
,
count1
+
count2
));
/* simply ignore the operator */
return
;
}
/* set-up new horizontal and vertical hint mask now */
error
=
ps_dimension_set_mask_bits
(
&
dim
[
0
],
bytes
,
count2
,
count1
,
end_point
,
memory
);
if
(
error
)
goto
Fail
;
error
=
ps_dimension_set_mask_bits
(
&
dim
[
1
],
bytes
,
0
,
count2
,
end_point
,
memory
);
if
(
error
)
goto
Fail
;
}
return
;
Fail
:
hints
->
error
=
error
;
}
static
void
ps_hints_t2counter
(
PS_Hints
hints
,
FT_UInt
bit_count
,
const
FT_Byte
*
bytes
)
{
FT_Error
error
;
if
(
!
hints
->
error
)
{
PS_Dimension
dim
=
hints
->
dimension
;
FT_Memory
memory
=
hints
->
memory
;
FT_UInt
count1
=
dim
[
0
].
hints
.
num_hints
;
FT_UInt
count2
=
dim
[
1
].
hints
.
num_hints
;
/* check bit count, must be equal to current total hint count */
if
(
bit_count
!=
count1
+
count2
)
{
FT_TRACE0
((
"ps_hints_t2counter:"
" called with invalid bitcount %d (instead of %d)
\n
"
,
bit_count
,
count1
+
count2
));
/* simply ignore the operator */
return
;
}
/* set-up new horizontal and vertical hint mask now */
error
=
ps_dimension_set_mask_bits
(
&
dim
[
0
],
bytes
,
0
,
count1
,
0
,
memory
);
if
(
error
)
goto
Fail
;
error
=
ps_dimension_set_mask_bits
(
&
dim
[
1
],
bytes
,
count1
,
count2
,
0
,
memory
);
if
(
error
)
goto
Fail
;
}
return
;
Fail
:
hints
->
error
=
error
;
}
/* end recording session */
static
FT_Error
ps_hints_close
(
PS_Hints
hints
,
FT_UInt
end_point
)
{
FT_Error
error
;
error
=
hints
->
error
;
if
(
!
error
)
{
FT_Memory
memory
=
hints
->
memory
;
PS_Dimension
dim
=
hints
->
dimension
;
error
=
ps_dimension_end
(
&
dim
[
0
],
end_point
,
memory
);
if
(
!
error
)
{
error
=
ps_dimension_end
(
&
dim
[
1
],
end_point
,
memory
);
}
}
#ifdef DEBUG_HINTER
if
(
!
error
)
ps_debug_hints
=
hints
;
#endif
return
error
;
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** TYPE 1 HINTS RECORDING INTERFACE *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
static
void
t1_hints_open
(
T1_Hints
hints
)
{
ps_hints_open
(
(
PS_Hints
)
hints
,
PS_HINT_TYPE_1
);
}
static
void
t1_hints_stem
(
T1_Hints
hints
,
FT_Int
dimension
,
FT_Fixed
*
coords
)
{
FT_Pos
stems
[
2
];
stems
[
0
]
=
FIXED_TO_INT
(
coords
[
0
]
);
stems
[
1
]
=
FIXED_TO_INT
(
coords
[
1
]
);
ps_hints_stem
(
(
PS_Hints
)
hints
,
dimension
,
1
,
stems
);
}
FT_LOCAL_DEF
(
void
)
t1_hints_funcs_init
(
T1_Hints_FuncsRec
*
funcs
)
{
FT_MEM_ZERO
(
(
char
*
)
funcs
,
sizeof
(
*
funcs
)
);
funcs
->
open
=
(
T1_Hints_OpenFunc
)
t1_hints_open
;
funcs
->
close
=
(
T1_Hints_CloseFunc
)
ps_hints_close
;
funcs
->
stem
=
(
T1_Hints_SetStemFunc
)
t1_hints_stem
;
funcs
->
stem3
=
(
T1_Hints_SetStem3Func
)
ps_hints_t1stem3
;
funcs
->
reset
=
(
T1_Hints_ResetFunc
)
ps_hints_t1reset
;
funcs
->
apply
=
(
T1_Hints_ApplyFunc
)
ps_hints_apply
;
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** TYPE 2 HINTS RECORDING INTERFACE *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
static
void
t2_hints_open
(
T2_Hints
hints
)
{
ps_hints_open
(
(
PS_Hints
)
hints
,
PS_HINT_TYPE_2
);
}
static
void
t2_hints_stems
(
T2_Hints
hints
,
FT_Int
dimension
,
FT_Int
count
,
FT_Fixed
*
coords
)
{
FT_Pos
stems
[
32
],
y
,
n
;
FT_Int
total
=
count
;
y
=
0
;
while
(
total
>
0
)
{
/* determine number of stems to write */
count
=
total
;
if
(
count
>
16
)
count
=
16
;
/* compute integer stem positions in font units */
for
(
n
=
0
;
n
<
count
*
2
;
n
++
)
{
y
+=
coords
[
n
];
stems
[
n
]
=
FIXED_TO_INT
(
y
);
}
/* compute lengths */
for
(
n
=
0
;
n
<
count
*
2
;
n
+=
2
)
stems
[
n
+
1
]
=
stems
[
n
+
1
]
-
stems
[
n
];
/* add them to the current dimension */
ps_hints_stem
(
(
PS_Hints
)
hints
,
dimension
,
count
,
stems
);
total
-=
count
;
}
}
FT_LOCAL_DEF
(
void
)
t2_hints_funcs_init
(
T2_Hints_FuncsRec
*
funcs
)
{
FT_MEM_ZERO
(
funcs
,
sizeof
(
*
funcs
)
);
funcs
->
open
=
(
T2_Hints_OpenFunc
)
t2_hints_open
;
funcs
->
close
=
(
T2_Hints_CloseFunc
)
ps_hints_close
;
funcs
->
stems
=
(
T2_Hints_StemsFunc
)
t2_hints_stems
;
funcs
->
hintmask
=
(
T2_Hints_MaskFunc
)
ps_hints_t2mask
;
funcs
->
counter
=
(
T2_Hints_CounterFunc
)
ps_hints_t2counter
;
funcs
->
apply
=
(
T2_Hints_ApplyFunc
)
ps_hints_apply
;
}
/* END */
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Sun, Nov 15, 11:13 AM (4 h, 7 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
152290
Default Alt Text
pshrec.c (31 KB)
Attached To
Mode
R80 StarRuler2-Source
Attached
Detach File
Event Timeline