// C++ code Copyright (C) David R. Evans G4AMJ/NQ0I // class for grey scale for laserwriter #include #include #include #include #include #include // constructor grey_font_laserwriter::grey_font_laserwriter(const uint16 width, const uint16 height) : grey_font(width, height) { bias = (w * h < 50 ? 65 : 0); heap_check(pr = new char* [w * h + 1]); _generate_squares(); } // destructor grey_font_laserwriter::~grey_font_laserwriter(void) { if (pr) then { for (int n = 0; n <= w * h; n++) { if (pr[n]) then delete [] pr[n]; } delete [] pr; } } uint16 grey_font_laserwriter::_rebuild(const uint16 width, const uint16 height) { if (pr) then { for (int n = 0; n <= w * h; n++) { if (pr[n]) then delete [] (pr[n]); } delete [] pr; } w = width; h = height; bias = (w * h < 50 ? 65 : 0); heap_check(pr = new char* [w * h + 1]); font_number = ++fonts_created; _generate_squares(); index = 0; return (width * height); }; // private -- generate a memory map of a single square void* grey_font_laserwriter::_generate_square(const uint16 n_black) { char *ptr; const int square_size = w * h, breakpoint = square_size / 2; int n_marked = 0, put_value, n_to_do, default_value = 1; // create the empty square and a pointer to it. Each byte can store eight // bits const int octets_per_square = (w * h) / 8 + ( ( (w * h) % 8 ) ? 1 : 0 ); heap_check(ptr = new char [octets_per_square]); // CAREFUL! // clear the characters for (int n = 0; n < octets_per_square; n++) ptr[n] = 0; if (n_black > breakpoint) then { for (int i = 0; i < w; i++) for (int j = 0; j < h; j++) _set_bit(ptr, i, j, default_value); put_value = 0; n_to_do = square_size - n_black; } else { put_value = default_value; n_to_do = n_black; } if (n_to_do) { for (int j = 1; n_marked < n_to_do; j++) { for (int i = 0; (i < square_size) && (n_marked < n_to_do); i++) { if ((_get_bit(ptr, i % w, i / w) != put_value) && ((rand() / (2147483648.0)) < (1.0 / (10.0 * w)))) { _set_bit(ptr, i % w, i / w, put_value); n_marked++; } } } } return ptr; } // private -- generate memory versions of all the squares void grey_font_laserwriter::_generate_squares(void) { for (int n_black = 0; n_black <= w * h; n_black++) pr[n_black] = _generate_square(n_black); } // private -- create the hex DREstring used to define a particular // character DREstring grey_font_laserwriter::_character_bitmap(const int n_black) { byte image_byte[MAX_SIZE]; char* ptr= pr[n_black]; const int bytes_per_line = (w - 1) / 8 + 1, total_bytes = bytes_per_line * h; DREstring rv; for (int n = 0; n < w * h; n++) image_byte[n] = 0; for (int row_nr = 0; row_nr < h; row_nr++) for (int column_nr = 0; column_nr < w; column_nr++) { if (_get_bit(ptr, column_nr, row_nr)) then { int byte_nr = row_nr * bytes_per_line + (column_nr / 8); image_byte[byte_nr] = image_byte[byte_nr] | (1 << (7 - (column_nr % 8))); } } // convert the array to a DREstring of hex characters rv = DREstring(image_byte[0], "%2.2X"); for (int byte_nr = 1; byte_nr < total_bytes; byte_nr++) rv += DREstring(image_byte[byte_nr], "%2.2X"); return rv; } // private -- generate a single PostScript character DREstring grey_font_laserwriter::_ps_character(const int n_black) { DREstring height_DREstring(h, 10), width_DREstring(w, 10), rv("/C"); const int n = n_black + bias, n1 = n % 26, n2 = (n / 26) % 26; DREstring id; id += (char)(65 + n2); id += (char)(65 + n1); rv += id; DREstring space(" "); rv += (DREstring)" [1 0 0 " + width_DREstring + space + height_DREstring + space + width_DREstring + space + height_DREstring + (DREstring)" 0 0 <" + _character_bitmap(n_black) + (DREstring)">] def"; return rv; }