hb_bool_t hb_ot_layout_language_find_feature (hb_face_t *face, hb_tag_t table_tag, unsigned int script_index, unsigned int language_index, hb_tag_t feature_tag, unsigned int *feature_index) { ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX); const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index); unsigned int num_features = l.get_feature_count (); for (unsigned int i = 0; i < num_features; i++) { unsigned int f_index = l.get_feature_index (i); if (feature_tag == g.get_feature_tag (f_index)) { if (feature_index) *feature_index = f_index; return true; } } if (feature_index) *feature_index = HB_OT_LAYOUT_NO_FEATURE_INDEX; return false; }
hb_bool_t hb_ot_layout_table_find_script (hb_face_t *face, hb_tag_t table_tag, hb_tag_t script_tag, unsigned int *script_index) { ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX); const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); if (g.find_script_index (script_tag, script_index)) return true; /* try finding 'DFLT' */ if (g.find_script_index (HB_OT_TAG_DEFAULT_SCRIPT, script_index)) return false; /* try with 'dflt'; MS site has had typos and many fonts use it now :(. * including many versions of DejaVu Sans Mono! */ if (g.find_script_index (HB_OT_TAG_DEFAULT_LANGUAGE, script_index)) return false; /* try with 'latn'; some old fonts put their features there even though they're really trying to support Thai, for example :( */ if (g.find_script_index (HB_OT_TAG_LATIN_SCRIPT, script_index)) return false; if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX; return false; }
hb_bool_t hb_ot_layout_table_choose_script (hb_face_t *face, hb_tag_t table_tag, const hb_tag_t *script_tags, unsigned int *script_index, hb_tag_t *chosen_script) { ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX); const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); while (*script_tags) { if (g.find_script_index (*script_tags, script_index)) { if (chosen_script) *chosen_script = *script_tags; return true; } script_tags++; } /* try finding 'DFLT' */ if (g.find_script_index (HB_OT_TAG_DEFAULT_SCRIPT, script_index)) { if (chosen_script) *chosen_script = HB_OT_TAG_DEFAULT_SCRIPT; return false; } /* try with 'dflt'; MS site has had typos and many fonts use it now :( */ if (g.find_script_index (HB_OT_TAG_DEFAULT_LANGUAGE, script_index)) { if (chosen_script) *chosen_script = HB_OT_TAG_DEFAULT_LANGUAGE; return false; } /* try with 'latn'; some old fonts put their features there even though they're really trying to support Thai, for example :( */ if (g.find_script_index (HB_OT_TAG_LATIN_SCRIPT, script_index)) { if (chosen_script) *chosen_script = HB_OT_TAG_LATIN_SCRIPT; return false; } if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX; if (chosen_script) *chosen_script = HB_OT_LAYOUT_NO_SCRIPT_INDEX; return false; }
bool hb_buffer_t::enlarge (unsigned int size) { if (unlikely (in_error)) return false; if (unlikely (size > max_len)) { in_error = true; return false; } unsigned int new_allocated = allocated; hb_glyph_position_t *new_pos = NULL; hb_glyph_info_t *new_info = NULL; bool separate_out = out_info != info; if (unlikely (_hb_unsigned_int_mul_overflows (size, sizeof (info[0])))) goto done; while (size >= new_allocated) new_allocated += (new_allocated >> 1) + 32; ASSERT_STATIC (sizeof (info[0]) == sizeof (pos[0])); if (unlikely (_hb_unsigned_int_mul_overflows (new_allocated, sizeof (info[0])))) goto done; new_pos = (hb_glyph_position_t *) realloc (pos, new_allocated * sizeof (pos[0])); new_info = (hb_glyph_info_t *) realloc (info, new_allocated * sizeof (info[0])); done: if (unlikely (!new_pos || !new_info)) in_error = true; if (likely (new_pos)) pos = new_pos; if (likely (new_info)) info = new_info; out_info = separate_out ? (hb_glyph_info_t *) pos : info; if (likely (!in_error)) allocated = new_allocated; return likely (!in_error); }
hb_bool_t hb_ot_layout_script_find_language (hb_face_t *face, hb_tag_t table_tag, unsigned int script_index, hb_tag_t language_tag, unsigned int *language_index) { ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX); const OT::Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index); if (s.find_lang_sys_index (language_tag, language_index)) return true; /* try with 'dflt'; MS site has had typos and many fonts use it now :( */ if (s.find_lang_sys_index (HB_OT_TAG_DEFAULT_LANGUAGE, language_index)) return false; if (language_index) *language_index = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX; return false; }
hb_bool_t hb_ot_layout_table_find_feature (hb_face_t *face, hb_tag_t table_tag, hb_tag_t feature_tag, unsigned int *feature_index) { ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX); const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); unsigned int num_features = g.get_feature_count (); for (unsigned int i = 0; i < num_features; i++) { if (feature_tag == g.get_feature_tag (i)) { if (feature_index) *feature_index = i; return true; } } if (feature_index) *feature_index = HB_OT_LAYOUT_NO_FEATURE_INDEX; return false; }
unsigned int hb_ot_layout_language_get_feature_tags (hb_face_t *face, hb_tag_t table_tag, unsigned int script_index, unsigned int language_index, unsigned int start_offset, unsigned int *feature_count /* IN/OUT */, hb_tag_t *feature_tags /* OUT */) { const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index); ASSERT_STATIC (sizeof (unsigned int) == sizeof (hb_tag_t)); unsigned int ret = l.get_feature_indexes (start_offset, feature_count, (unsigned int *) feature_tags); if (feature_tags) { unsigned int count = *feature_count; for (unsigned int i = 0; i < count; i++) feature_tags[i] = g.get_feature_tag ((unsigned int) feature_tags[i]); } return ret; }
bool utTextureLoadKTX( const char *data, int size, utTextureInfo* info ) { ASSERT_STATIC( sizeof( KTXHeader ) == 64 ); info->_surfaces = NULL; memcpy( &ktxHeader, data, 64 ); // Check header if( memcmp(ktxHeader.identifier, ktxIdentifier, 12) !=0 ) { Modules::log().writeError( "Invalid KTX header" ); return false; } // Store properties info->_width = ktxHeader.pixelWidth; info->_height = ktxHeader.pixelHeight; info->_depth = 1; info->_format = utTextureFormats::Unknown; info->_mipCount = ktxHeader.numberOfMipmapLevels; // Get texture type if( ktxHeader.numberOfFaces > 1 ) { if( ktxHeader.numberOfFaces != 6 ) { Modules::log().writeError( "Wrong number of cube texture faces (should be 6)" ); return false; } else { info->_type = utTextureTypes::TexCube; } } else if( ktxHeader.pixelDepth > 1 ) { info->_depth = ktxHeader.pixelDepth; info->_type = utTextureTypes::Tex3D; } else info->_type = utTextureTypes::Tex2D; // Texture arrays are not supported yet if( ktxHeader.numberOfArrayElements > 1 ) { Modules::log().writeWarning( "Texture Arrays not supported. using first array element only" ); } // Get pixel format switch( ktxHeader.glInternalFormat ) { case GL_RGB8: info->_format = utTextureFormats::RGB8; break; case GL_RGBA8: info->_format = utTextureFormats::BGRA8; break; case GL_BGRA: info->_format = utTextureFormats::BGRA8; break; case GL_RGBA16F: info->_format = utTextureFormats::RGBA16F; break; case GL_RGBA32F: info->_format = utTextureFormats::RGBA32F; break; case GL_COMPRESSED_RGBA_S3TC_DXT1: info->_format = utTextureFormats::DXT1; break; case GL_COMPRESSED_RGBA_S3TC_DXT3: info->_format = utTextureFormats::DXT3; break; case GL_COMPRESSED_RGBA_S3TC_DXT5: info->_format = utTextureFormats::DXT5; break; case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG: info->_format = utTextureFormats::PVRTCI_2BPP; break; case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: info->_format = utTextureFormats::PVRTCI_A2BPP; break; case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG: info->_format = utTextureFormats::PVRTCI_4BPP; break; case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: info->_format = utTextureFormats::PVRTCI_A4BPP; break; case GL_ETC1_RGB8_OES: info->_format = utTextureFormats::ETC1; break; } if( info->_format == utTextureFormats::Unknown ) { Modules::log().writeError( "Unsupported KTX pixel format" ); return false; } info->_sliceCount = info->_type == utTextureTypes::TexCube ? 6 : 1; unsigned char *pixels = (unsigned char *)(data + 128); uint32 surfaceIndex = 0; info->_surfaceCount = info->_sliceCount * info->_mipCount; info->_surfaces = new utTextureSurfaceInfo[info->_surfaceCount]; int width = info->_width, height = info->_height, depth = info->_depth; for( uint32 i = 0; i < info->_mipCount; ++i ) { size_t mipSize = calcTextureSize( info->_format, width, height, depth ); if( pixels + mipSize > (unsigned char *)data + size ) { Modules::log().writeError( "Corrupt KTX" ); return false; } for( uint32 j = 0; j < ktxHeader.numberOfArrayElements; ++j ) { for( uint32 k = 0; k < ktxHeader.numberOfFaces; ++k ) { if ( j == 0) { // using only first element of array now utTextureSurfaceInfo& surface = info->_surfaces[surfaceIndex++]; surface._mip = i; surface._slice = k; surface._data = pixels; surface._size = (uint32)mipSize; } pixels += mipSize; } } if( width > 1 ) width >>= 1; if( height > 1 ) height >>= 1; if( depth > 1 ) depth >>= 1; } ASSERT( pixels == (unsigned char *)data + size ); return true; }
bool utTextureLoadPVR( const char* data, uint32 size, utTextureInfo* info) { // Load pvr ASSERT_STATIC( sizeof( PVRHeader ) == 52 ); info->_surfaces = NULL; memcpy( &pvrHeader, data, 52 ); // Store properties info->_width = pvrHeader.dwWidth; info->_height = pvrHeader.dwHeight; info->_depth = 1; info->_format = utTextureFormats::Unknown; info->_mipCount = pvrHeader.dwMipMapCount; // Get texture type if( pvrHeader.dwNumFaces == 6 ) { info->_type = utTextureTypes::TexCube; } else { info->_type = utTextureTypes::Tex2D; } // Get pixel format if (pvrHeader.dwPixelFormatHigh == 0 ) { switch(pvrHeader.dwPixelFormatLow) { case ePVRTPF_PVRTCI_2bpp_RGBA: info->_format = utTextureFormats::PVRTCI_A2BPP; break; case ePVRTPF_PVRTCI_4bpp_RGBA: info->_format = utTextureFormats::PVRTCI_A4BPP; break; case ePVRTPF_DXT1: info->_format = utTextureFormats::DXT1; break; case ePVRTPF_DXT3: info->_format = utTextureFormats::DXT3; break; case ePVRTPF_DXT5: info->_format = utTextureFormats::DXT5; break; case ePVRTPF_PVRTCI_2bpp_RGB: info->_format = utTextureFormats::PVRTCI_2BPP; break; case ePVRTPF_PVRTCI_4bpp_RGB: info->_format = utTextureFormats::PVRTCI_4BPP; break; case ePVRTPF_ETC1: info->_format = utTextureFormats::ETC1; break; } } if( info->_format == utTextureFormats::Unknown ) { Modules().log().writeError( "Unsupported PVR pixel format" ); return false; } // Upload texture subresources info->_sliceCount = info->_type == utTextureTypes::TexCube ? 6 : 1; unsigned char *pixels = (unsigned char *)(data + 52); uint32 surfaceIndex = 0; info->_surfaceCount = info->_sliceCount * info->_mipCount; info->_surfaces = new utTextureSurfaceInfo[info->_surfaceCount]; for( uint32 i = 0; i < info->_sliceCount; ++i ) { int width = pvrHeader.dwWidth, height = pvrHeader.dwHeight; for( uint32 j = 0; j < info->_mipCount; ++j ) { size_t mipSize = calcTextureSize( info->_format, width, height, 1 ); if( pixels + mipSize > (unsigned char *)data + size ) { Modules::log().writeError( "Corrupt PVR" ); return false; } utTextureSurfaceInfo& surface = info->_surfaces[surfaceIndex++]; surface._mip = j; surface._slice = i; surface._data = pixels; surface._size = (uint32)mipSize; pixels += mipSize; if( width > 1 ) width >>= 1; if( height > 1 ) height >>= 1; } } ASSERT( pixels == (unsigned char *)data + size); return true; }