00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "Core/precomp.h"
00020
00021 #include <API/Core/System/cl_assert.h>
00022 #include <API/Core/System/error.h>
00023 #include <API/Display/Font/font_description.h>
00024 #include <API/Display/Font/font.h>
00025 #include <API/Display/Display/surfaceprovider.h>
00026 #include <API/Display/Display/palette.h>
00027 #include <Display/Font/resource_font_generic.h>
00028 #include <Display/Font/resourcetype_font.h>
00029 #include <Display/Display/Generic/restype_surface.h>
00030
00031
00032
00033
00034
00035 CL_Res_Font::CL_Res_Font() : CL_Res_Font_Generic("font")
00036 {
00037 }
00038
00039 CL_Resource *CL_Res_Font::create_from_location(
00040 std::string name,
00041 std::string location,
00042 CL_ResourceOptions *options,
00043 CL_ResourceManager *parent)
00044 {
00045 CL_String ext = CL_String(location).right(4);
00046 ext.to_lower();
00047
00048 bool is_font_type = false;
00049 if (options->exists("type"))
00050 {
00051 if (options->get_value("type") != "font") return NULL;
00052 is_font_type = true;
00053 }
00054
00055 if (is_font_type || options->exists("font"))
00056 {
00057 return new CL_Font_Resource(
00058 name,
00059 location,
00060 options,
00061 parent);
00062 }
00063
00064 return NULL;
00065 }
00066
00067 CL_Resource *CL_Res_Font::create_from_serialization(
00068 std::string name,
00069 CL_ResourceManager *parent)
00070 {
00071 return new CL_Font_Resource(
00072 name,
00073 parent);
00074 }
00075
00076
00077
00078
00079 CL_Font_Resource::CL_Font_Resource(
00080 std::string name,
00081 std::string location,
00082 CL_ResourceOptions *options,
00083 CL_ResourceManager *parent)
00084 : CL_Font_Resource_Generic("font", name)
00085 {
00086 this->location = location;
00087 this->options = options;
00088 this->parent = parent;
00089 from_datafile = false;
00090 load_count = 0;
00091
00092 font = NULL;
00093 font_desc = NULL;
00094 }
00095
00096 CL_Font_Resource::CL_Font_Resource(
00097 std::string name,
00098 CL_ResourceManager *parent)
00099 : CL_Font_Resource_Generic("font", name)
00100 {
00101 location = "";
00102 options = NULL;
00103 this->parent = parent;
00104 from_datafile = true;
00105 load_count = 0;
00106
00107 font = NULL;
00108 font_desc = NULL;
00109 }
00110
00111 CL_Font_Resource::~CL_Font_Resource()
00112 {
00113 delete options;
00114
00115 }
00116
00117 void CL_Font_Resource::serialize_save(CL_OutputSource *output)
00118 {
00119 load_count++;
00120 if (font_desc != NULL) return;
00121
00122 if (from_datafile) load_from_datafile();
00123 else load_from_file();
00124
00125 output->write_int32(font_desc->space_len);
00126 output->write_int32(font_desc->subtract_width);
00127 output->write_string(font_desc->letters.c_str());
00128
00129
00130
00131
00132 unsigned int len = font_desc->letters.length();
00133 if (len > font_desc->letter_providers.size())
00134 {
00135 CL_String err;
00136 err << "Font loading error - ";
00137 err << "Letters expected: " << len;
00138 err << ", letters available: " << CL_String((int) font_desc->letter_providers.size());
00139
00140 throw CL_Error(err.get_string());
00141 }
00142 else if (len < font_desc->letter_providers.size())
00143 {
00144 std::cout << "ClanLib Font Warning: Font letters do not match!" << std::endl;
00145 std::cout << "ClanLib Font Warning: Letters expected: " << len << std::endl;
00146 std::cout << "ClanLib Font Warning: Letters available: "
00147 << font_desc->letter_providers.size() << std::endl;
00148 }
00149
00150 if (len > 0)
00151 {
00152 font_desc->letter_providers[0]->lock();
00153 }
00154 for(unsigned int i=0; i<len; i++)
00155 {
00156 CL_SurfaceProvider *provider = font_desc->letter_providers[i];
00157 cl_assert(provider != NULL);
00158
00159 provider->lock();
00160
00161 int width = provider->get_width();
00162 int height = provider->get_height();
00163 int no_sprs = provider->get_num_frames();
00164 int bytes_per_pixel = (provider->get_depth()+7)/8;
00165 int transcol = provider->uses_src_colorkey() ? (int)provider->get_src_colorkey() : -1;
00166
00167 int red_mask = provider->get_red_mask();
00168 int green_mask = provider->get_green_mask();
00169 int blue_mask = provider->get_blue_mask();
00170 int alpha_mask = provider->get_alpha_mask();
00171 int translate_x = provider->get_translate_x();
00172 int translate_y = provider->get_translate_y();
00173 int pitch = provider->get_pitch();
00174
00175 CL_Palette *pal = provider->get_palette();
00176 unsigned char *data = (unsigned char *) provider->get_data();
00177 cl_assert(data != NULL);
00178
00179 output->write_int32(width);
00180 output->write_int32(height);
00181 output->write_int32(no_sprs);
00182 output->write_int32(transcol);
00183
00184 char palette_bool = (pal != NULL) ? 1 : 0;
00185 output->write_char8(palette_bool);
00186
00187 if (palette_bool) output->write(pal->palette, 256*3);
00188
00189 char indexed_bool = (provider->is_indexed()) ? 1 : 0;
00190 output->write_char8(indexed_bool);
00191
00192
00193 output->write_int32(red_mask);
00194 output->write_int32(green_mask);
00195 output->write_int32(blue_mask);
00196 output->write_int32(alpha_mask);
00197 output->write_int32(provider->get_depth());
00198
00199 if (transcol == -1)
00200 {
00201 int bytes_pr_line = width*bytes_per_pixel;
00202 for (int y=0; y<height*no_sprs; y++)
00203 {
00204 int img_y = y+translate_y;
00205
00206 output->write(
00207 data+translate_x*bytes_per_pixel+img_y*pitch,
00208 bytes_pr_line);
00209 }
00210 }
00211 else
00212 {
00213 for (int y=0; y<height*no_sprs; y++)
00214 {
00215 int img_y = y+translate_y;
00216
00217 output->write(
00218 data+translate_x*bytes_per_pixel+img_y*pitch,
00219 bytes_per_pixel*width);
00220 }
00221 }
00222
00223 provider->unlock();
00224 }
00225 if (len > 0)
00226 {
00227 font_desc->letter_providers[0]->unlock();
00228 }
00229
00230 unload();
00231 }
00232
00233 void CL_Font_Resource::load()
00234 {
00235 load_count++;
00236 if (font_desc != NULL) return;
00237
00238 if (from_datafile) load_from_datafile();
00239 else load_from_file();
00240
00241 font = new CL_Font(font_desc);
00242 }
00243
00244 void CL_Font_Resource::unload()
00245 {
00246 load_count--;
00247 if (load_count == 0)
00248 {
00249 delete font_desc;
00250 font_desc = NULL;
00251 delete font;
00252 font = NULL;
00253 }
00254 }
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264 void CL_Font_Resource::load_from_datafile()
00265 {
00266 CL_InputSourceProvider *provider = parent->get_resource_provider();
00267
00268 font_desc = new CL_Font_Description(
00269 provider->open_source(get_name().c_str()));
00270 }
00271
00272 void CL_Font_Resource::load_from_file()
00273 {
00274 CL_String ext = CL_String(location).right(4);
00275 ext.to_lower();
00276
00277
00278
00279 if (ext == ".tga" || options->exists("alphafont")
00280 || (ext == ".png" && options->exists("alphafont")))
00281 {
00282 if (options->exists("spacelen") == false)
00283 throw CL_Error("Font missing spacelen option.");
00284
00285 if (options->exists("trans_limit") == false)
00286 throw CL_Error("Font missing trans_limit option.");
00287
00288 if (options->exists("subtract_width") == false)
00289 throw CL_Error("Font missing subtract_width option.");
00290
00291 if (options->exists("letters") == false)
00292 throw CL_Error("Font missing letters option.");
00293
00294 int space_len = CL_String(options->get_value("spacelen")).get_as_int();
00295 float trans_limit = CL_String(options->get_value("trans_limit")).get_as_float();
00296 int subtract_width = CL_String(options->get_value("subtract_width")).get_as_int();
00297 CL_SurfaceProvider* provider = 0;
00298
00299 for (std::list<CL_ResourceSource_Surface*>::iterator it = CL_Res_Surface::surface_sources.begin();
00300 it != CL_Res_Surface::surface_sources.end();
00301 it++)
00302 {
00303 if ((*it)->can_create (ext, options))
00304 {
00305 provider = (*it)->create (location, options, parent);
00306 break;
00307 }
00308 }
00309 cl_assert (provider != NULL);
00310
00311 font_desc = new CL_Font_Description(provider,
00312 trans_limit,
00313 space_len,
00314 subtract_width,
00315 options->get_value("letters").c_str());
00316 }
00317 else
00318 {
00319 if (options->exists("x") == false)
00320 throw CL_Error("Font missing x coordinate option.");
00321
00322 if (options->exists("y") == false)
00323 throw CL_Error("Font missing y coordinate option.");
00324
00325 if (options->exists("spacelen") == false)
00326 throw CL_Error("Font missing spacelen option.");
00327
00328 if (options->exists("letters") == false)
00329 throw CL_Error("Font missing letters option.");
00330
00331 int x = CL_String(options->get_value("x")).get_as_int();
00332 int y = CL_String(options->get_value("y")).get_as_int();
00333 int space_len = CL_String(options->get_value("spacelen")).get_as_int();
00334 int subtract_width = 0;
00335 if (options->exists("subtract_width"))
00336 subtract_width = CL_String(
00337 options->get_value("subtract_width")).get_as_int();
00338
00339 int num_tcols = 1;
00340 int *tcols = NULL;
00341 if (num_tcols > 0)
00342 {
00343 tcols = new int[num_tcols];
00344 tcols[0] = 0;
00345 }
00346
00347 CL_SurfaceProvider* provider = 0;
00348
00349 for (std::list<CL_ResourceSource_Surface*>::iterator it = CL_Res_Surface::surface_sources.begin();
00350 it != CL_Res_Surface::surface_sources.end();
00351 it++)
00352 {
00353 if ((*it)->can_create (ext, options))
00354 {
00355 provider = (*it)->create (location, options, parent);
00356 break;
00357 }
00358 }
00359 cl_assert (provider != NULL);
00360
00361 font_desc = new CL_Font_Description(provider,
00362 x, y,
00363 tcols, num_tcols,
00364 space_len,
00365 subtract_width,
00366 options->get_value("letters").c_str());
00367 }
00368 }