24PNMTextGlyph(
double advance) :
29 _int_advance = (int)floor(_advance + 0.5);
46place(
PNMImage &dest_image,
int xp,
int yp,
const LColor &fg) {
47 if (!_image.is_valid()) {
52 LColorf fgf = LCAST(
float, fg);
54 int left = xp + _left;
56 int right = left + _image.get_x_size();
57 int bottom = top + _image.get_y_size();
60 int cleft = max(left, 0);
61 int ctop = max(top, 0);
62 int cright = min(right, dest_image.
get_x_size());
63 int cbottom = min(bottom, dest_image.
get_y_size());
65 for (
int y = ctop; y < cbottom; y++) {
66 for (
int x = cleft; x < cright; x++) {
67 double gval =
get_value(x - left, y - top);
71 }
else if (gval > 0.0) {
73 dest_image.
set_xel_a(x, y, fgf * gval + bg * (1.0 - gval));
85 const LColor &interior) {
86 if (!_image.is_valid()) {
91 LColorf fgf = LCAST(
float, fg);
92 LColorf interiorf = LCAST(
float, interior);
94 int left = xp + _left;
96 int right = left + _image.get_x_size();
97 int bottom = top + _image.get_y_size();
100 int cleft = max(left, 0);
101 int ctop = max(top, 0);
102 int cright = min(right, dest_image.
get_x_size());
103 int cbottom = min(bottom, dest_image.
get_y_size());
105 for (
int y = ctop; y < cbottom; y++) {
106 for (
int x = cleft; x < cright; x++) {
107 double gval =
get_value(x - left, y - top);
111 }
else if (gval > 0.0) {
120 dest_image.
set_xel_a(x, y, fgf * gval + bg * (1.0 - gval));
138determine_interior() {
144 for (
int yi = 0; yi < y_size; yi++) {
145 for (
int xi = 0; xi < x_size; xi++) {
154 _scan_interior_points.clear();
155 for (
int yi = 0; yi < y_size; yi++) {
156 scan_interior(0, yi, 0,
false, 0);
157 scan_interior(x_size - 1, yi, 0,
false, 0);
159 for (
int xi = 0; xi < x_size; xi++) {
160 scan_interior(xi, 0, 0,
false, 0);
161 scan_interior(xi, y_size - 1, 0,
false, 0);
166 while (!_scan_interior_points.empty()) {
167 int index = _scan_interior_points.back();
168 _scan_interior_points.pop_back();
169 int y = index / _image.get_x_size();
170 int x = index % _image.get_x_size();
171 xelval new_code = _image.get_red_val(x, y);
172 bool this_dark = (_image.get_blue_val(x, y) > 0);
174 scan_interior(x - 1, y, new_code, this_dark, 0);
175 scan_interior(x, y - 1, new_code, this_dark, 0);
176 scan_interior(x + 1, y, new_code, this_dark, 0);
177 scan_interior(x, y + 1, new_code, this_dark, 0);
179 _scan_interior_points.clear();
184 for (
int yi = 0; yi < y_size; yi++) {
185 for (
int xi = 0; xi < x_size; xi++) {
186 xelval code = _image.get_red_val(xi, yi);
187 if (((code + 2) & 0x3) == 0) {
188 _image.set_red_val(xi, yi, maxval);
190 _image.set_red_val(xi, yi, 0);
202scan_interior(
int x,
int y, xelval new_code,
bool neighbor_dark,
204 if (x < 0 || y < 0 || x >= _image.get_x_size() || y >= _image.get_y_size()) {
207 bool this_dark = (_image.get_blue_val(x, y) > 0);
208 if (this_dark != neighbor_dark) {
210 if (new_code < _image.get_maxval()) {
213 nassertv(new_code > 0);
216 if (new_code < _image.get_red_val(x, y)) {
217 _image.set_red_val(x, y, new_code);
219 if (recurse_level > 1024) {
223 int index = y * _image.get_x_size() + x;
224 _scan_interior_points.push_back(index);
227 scan_interior(x - 1, y, new_code, this_dark, recurse_level);
228 scan_interior(x, y - 1, new_code, this_dark, recurse_level);
229 scan_interior(x + 1, y, new_code, this_dark, recurse_level);
230 scan_interior(x, y + 1, new_code, this_dark, recurse_level);
240rescale(
double scale_factor) {
241 if (scale_factor == 1.0) {
244 nassertv(scale_factor != 0.0);
245 _advance /= scale_factor;
246 _int_advance = (int)floor(_advance + 0.5);
248 if (_image.is_valid()) {
249 int orig_x_size = _image.get_x_size();
250 int orig_y_size = _image.get_y_size();
251 int orig_left = _left;
256 int extra_pad = (int)ceil(scale_factor);
257 orig_x_size += 2*extra_pad;
258 orig_y_size += 2*extra_pad;
259 orig_left -= extra_pad;
260 orig_top += extra_pad;
263 int new_x_size = (int)ceil(orig_x_size / scale_factor);
264 int new_y_size = (int)ceil(orig_y_size / scale_factor);
265 int new_left = (int)floor(orig_left / scale_factor);
266 int new_top = (int)ceil(orig_top / scale_factor);
271 int old_x_size = (int)(new_x_size * scale_factor + 0.5);
272 int old_y_size = (int)(new_y_size * scale_factor + 0.5);
273 int old_left = (int)(new_left * scale_factor + 0.5);
274 int old_top = (int)(new_top * scale_factor + 0.5);
276 int pad_left = orig_left - old_left;
277 int pad_top = old_top - orig_top;
280 nassertv(extra_pad + pad_left >= 0 && extra_pad + pad_top >= 0);
282 PNMImage enlarged(old_x_size, old_y_size, _image.get_num_channels());
283 enlarged.copy_sub_image(_image, pad_left + extra_pad, pad_top + extra_pad);
285 _image.clear(new_x_size, new_y_size, _image.get_num_channels());
286 _image.quick_filter_from(enlarged);
The name of this class derives from the fact that we originally implemented it as a layer on top of t...
void set_xel_a(int x, int y, const LColorf &value)
Changes the RGBA color at the indicated pixel.
LColorf get_xel_a(int x, int y) const
Returns the RGBA color at the indicated pixel.
void set_red_val(int x, int y, xelval r)
Sets the red component color only at the indicated pixel.
bool get_interior_flag(int x, int y) const
Returns true if the indicated pixel represents a pixel in the interior of a hollow font,...
void place(PNMImage &dest_image, int xp, int yp, const LColor &fg)
Copies the glyph to the indicated destination image at the indicated origin.
double get_value(int x, int y) const
Returns the value of the indicated pixel of the glyph.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.