You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-14 13:41:12 +00:00
[TextServer] Add function to change font, font size, and OpenType features without invalidating line break points, justification points, or recreating shaped text buffer.
This commit is contained in:
@@ -91,7 +91,7 @@ void TextServerFallback::free(RID p_rid) {
|
||||
font_owner.free(p_rid);
|
||||
memdelete(fd);
|
||||
} else if (shaped_owner.owns(p_rid)) {
|
||||
ShapedTextData *sd = shaped_owner.get_or_null(p_rid);
|
||||
ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_rid);
|
||||
shaped_owner.free(p_rid);
|
||||
memdelete(sd);
|
||||
}
|
||||
@@ -2061,7 +2061,7 @@ void TextServerFallback::font_set_global_oversampling(float p_oversampling) {
|
||||
/* Shaped text buffer interface */
|
||||
/*************************************************************************/
|
||||
|
||||
void TextServerFallback::invalidate(ShapedTextData *p_shaped) {
|
||||
void TextServerFallback::invalidate(ShapedTextDataFallback *p_shaped) {
|
||||
p_shaped->valid = false;
|
||||
p_shaped->sort_valid = false;
|
||||
p_shaped->line_breaks_valid = false;
|
||||
@@ -2075,17 +2075,17 @@ void TextServerFallback::invalidate(ShapedTextData *p_shaped) {
|
||||
p_shaped->glyphs_logical.clear();
|
||||
}
|
||||
|
||||
void TextServerFallback::full_copy(ShapedTextData *p_shaped) {
|
||||
ShapedTextData *parent = shaped_owner.get_or_null(p_shaped->parent);
|
||||
void TextServerFallback::full_copy(ShapedTextDataFallback *p_shaped) {
|
||||
ShapedTextDataFallback *parent = shaped_owner.get_or_null(p_shaped->parent);
|
||||
|
||||
for (const KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : parent->objects) {
|
||||
for (const KeyValue<Variant, ShapedTextDataFallback::EmbeddedObject> &E : parent->objects) {
|
||||
if (E.value.pos >= p_shaped->start && E.value.pos < p_shaped->end) {
|
||||
p_shaped->objects[E.key] = E.value;
|
||||
}
|
||||
}
|
||||
|
||||
for (int k = 0; k < parent->spans.size(); k++) {
|
||||
ShapedTextData::Span span = parent->spans[k];
|
||||
ShapedTextDataFallback::Span span = parent->spans[k];
|
||||
if (span.start >= p_shaped->end || span.end <= p_shaped->start) {
|
||||
continue;
|
||||
}
|
||||
@@ -2099,7 +2099,7 @@ void TextServerFallback::full_copy(ShapedTextData *p_shaped) {
|
||||
|
||||
RID TextServerFallback::create_shaped_text(TextServer::Direction p_direction, TextServer::Orientation p_orientation) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
ShapedTextData *sd = memnew(ShapedTextData);
|
||||
ShapedTextDataFallback *sd = memnew(ShapedTextDataFallback);
|
||||
sd->direction = p_direction;
|
||||
sd->orientation = p_orientation;
|
||||
|
||||
@@ -2107,7 +2107,7 @@ RID TextServerFallback::create_shaped_text(TextServer::Direction p_direction, Te
|
||||
}
|
||||
|
||||
void TextServerFallback::shaped_text_clear(RID p_shaped) {
|
||||
ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND(!sd);
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
@@ -2136,7 +2136,7 @@ TextServer::Direction TextServerFallback::shaped_text_get_inferred_direction(RID
|
||||
|
||||
void TextServerFallback::shaped_text_set_custom_punctuation(RID p_shaped, const String &p_punct) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND(!sd);
|
||||
|
||||
if (sd->custom_punct != p_punct) {
|
||||
@@ -2150,13 +2150,13 @@ void TextServerFallback::shaped_text_set_custom_punctuation(RID p_shaped, const
|
||||
|
||||
String TextServerFallback::shaped_text_get_custom_punctuation(RID p_shaped) const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
const ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V(!sd, String());
|
||||
return sd->custom_punct;
|
||||
}
|
||||
|
||||
void TextServerFallback::shaped_text_set_orientation(RID p_shaped, TextServer::Orientation p_orientation) {
|
||||
ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND(!sd);
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
@@ -2174,7 +2174,7 @@ void TextServerFallback::shaped_text_set_bidi_override(RID p_shaped, const Array
|
||||
}
|
||||
|
||||
TextServer::Orientation TextServerFallback::shaped_text_get_orientation(RID p_shaped) const {
|
||||
const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
const ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V(!sd, TextServer::ORIENTATION_HORIZONTAL);
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
@@ -2182,7 +2182,7 @@ TextServer::Orientation TextServerFallback::shaped_text_get_orientation(RID p_sh
|
||||
}
|
||||
|
||||
void TextServerFallback::shaped_text_set_preserve_invalid(RID p_shaped, bool p_enabled) {
|
||||
ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
ERR_FAIL_COND(!sd);
|
||||
@@ -2196,7 +2196,7 @@ void TextServerFallback::shaped_text_set_preserve_invalid(RID p_shaped, bool p_e
|
||||
}
|
||||
|
||||
bool TextServerFallback::shaped_text_get_preserve_invalid(RID p_shaped) const {
|
||||
const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
const ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V(!sd, false);
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
@@ -2204,7 +2204,7 @@ bool TextServerFallback::shaped_text_get_preserve_invalid(RID p_shaped) const {
|
||||
}
|
||||
|
||||
void TextServerFallback::shaped_text_set_preserve_control(RID p_shaped, bool p_enabled) {
|
||||
ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND(!sd);
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
@@ -2218,15 +2218,52 @@ void TextServerFallback::shaped_text_set_preserve_control(RID p_shaped, bool p_e
|
||||
}
|
||||
|
||||
bool TextServerFallback::shaped_text_get_preserve_control(RID p_shaped) const {
|
||||
const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
const ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V(!sd, false);
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
return sd->preserve_control;
|
||||
}
|
||||
|
||||
bool TextServerFallback::shaped_text_add_string(RID p_shaped, const String &p_text, const Vector<RID> &p_fonts, int p_size, const Dictionary &p_opentype_features, const String &p_language) {
|
||||
ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
int TextServerFallback::shaped_get_span_count(RID p_shaped) const {
|
||||
ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V(!sd, 0);
|
||||
return sd->spans.size();
|
||||
}
|
||||
|
||||
Variant TextServerFallback::shaped_get_span_meta(RID p_shaped, int p_index) const {
|
||||
ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V(!sd, Variant());
|
||||
ERR_FAIL_INDEX_V(p_index, sd->spans.size(), Variant());
|
||||
return sd->spans[p_index].meta;
|
||||
}
|
||||
|
||||
void TextServerFallback::shaped_set_span_update_font(RID p_shaped, int p_index, const Vector<RID> &p_fonts, int p_size, const Dictionary &p_opentype_features) {
|
||||
ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND(!sd);
|
||||
ERR_FAIL_INDEX(p_index, sd->spans.size());
|
||||
|
||||
ShapedTextDataFallback::Span &span = sd->spans.write[p_index];
|
||||
span.fonts.clear();
|
||||
// Pre-sort fonts, push fonts with the language support first.
|
||||
Vector<RID> fonts_no_match;
|
||||
int font_count = p_fonts.size();
|
||||
for (int i = 0; i < font_count; i++) {
|
||||
if (font_is_language_supported(p_fonts[i], span.language)) {
|
||||
span.fonts.push_back(p_fonts[i]);
|
||||
} else {
|
||||
fonts_no_match.push_back(p_fonts[i]);
|
||||
}
|
||||
}
|
||||
span.fonts.append_array(fonts_no_match);
|
||||
span.font_size = p_size;
|
||||
span.features = p_opentype_features;
|
||||
|
||||
sd->valid = false;
|
||||
}
|
||||
|
||||
bool TextServerFallback::shaped_text_add_string(RID p_shaped, const String &p_text, const Vector<RID> &p_fonts, int p_size, const Dictionary &p_opentype_features, const String &p_language, const Variant &p_meta) {
|
||||
ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V(!sd, false);
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
@@ -2244,7 +2281,7 @@ bool TextServerFallback::shaped_text_add_string(RID p_shaped, const String &p_te
|
||||
full_copy(sd);
|
||||
}
|
||||
|
||||
ShapedTextData::Span span;
|
||||
ShapedTextDataFallback::Span span;
|
||||
span.start = sd->text.length();
|
||||
span.end = span.start + p_text.length();
|
||||
|
||||
@@ -2263,6 +2300,7 @@ bool TextServerFallback::shaped_text_add_string(RID p_shaped, const String &p_te
|
||||
ERR_FAIL_COND_V(span.fonts.is_empty(), false);
|
||||
span.font_size = p_size;
|
||||
span.language = p_language;
|
||||
span.meta = p_meta;
|
||||
|
||||
sd->spans.push_back(span);
|
||||
sd->text += p_text;
|
||||
@@ -2273,7 +2311,7 @@ bool TextServerFallback::shaped_text_add_string(RID p_shaped, const String &p_te
|
||||
}
|
||||
|
||||
bool TextServerFallback::shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align, int p_length) {
|
||||
ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V(!sd, false);
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
@@ -2284,12 +2322,12 @@ bool TextServerFallback::shaped_text_add_object(RID p_shaped, Variant p_key, con
|
||||
full_copy(sd);
|
||||
}
|
||||
|
||||
ShapedTextData::Span span;
|
||||
ShapedTextDataFallback::Span span;
|
||||
span.start = sd->start + sd->text.length();
|
||||
span.end = span.start + p_length;
|
||||
span.embedded_key = p_key;
|
||||
|
||||
ShapedTextData::EmbeddedObject obj;
|
||||
ShapedTextDataFallback::EmbeddedObject obj;
|
||||
obj.inline_align = p_inline_align;
|
||||
obj.rect.size = p_size;
|
||||
obj.pos = span.start;
|
||||
@@ -2304,7 +2342,7 @@ bool TextServerFallback::shaped_text_add_object(RID p_shaped, Variant p_key, con
|
||||
}
|
||||
|
||||
bool TextServerFallback::shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align) {
|
||||
ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V(!sd, false);
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
@@ -2324,7 +2362,7 @@ bool TextServerFallback::shaped_text_resize_object(RID p_shaped, Variant p_key,
|
||||
Glyph gl = sd->glyphs[i];
|
||||
Variant key;
|
||||
if (gl.count == 1) {
|
||||
for (const KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : sd->objects) {
|
||||
for (const KeyValue<Variant, ShapedTextDataFallback::EmbeddedObject> &E : sd->objects) {
|
||||
if (E.value.pos == gl.start) {
|
||||
key = E.key;
|
||||
break;
|
||||
@@ -2364,79 +2402,82 @@ bool TextServerFallback::shaped_text_resize_object(RID p_shaped, Variant p_key,
|
||||
sd->width += gl.advance * gl.repeat;
|
||||
}
|
||||
}
|
||||
|
||||
// Align embedded objects to baseline.
|
||||
float full_ascent = sd->ascent;
|
||||
float full_descent = sd->descent;
|
||||
for (KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : sd->objects) {
|
||||
if ((E.value.pos >= sd->start) && (E.value.pos < sd->end)) {
|
||||
if (sd->orientation == ORIENTATION_HORIZONTAL) {
|
||||
switch (E.value.inline_align & INLINE_ALIGNMENT_TEXT_MASK) {
|
||||
case INLINE_ALIGNMENT_TO_TOP: {
|
||||
E.value.rect.position.y = -sd->ascent;
|
||||
} break;
|
||||
case INLINE_ALIGNMENT_TO_CENTER: {
|
||||
E.value.rect.position.y = (-sd->ascent + sd->descent) / 2;
|
||||
} break;
|
||||
case INLINE_ALIGNMENT_TO_BASELINE: {
|
||||
E.value.rect.position.y = 0;
|
||||
} break;
|
||||
case INLINE_ALIGNMENT_TO_BOTTOM: {
|
||||
E.value.rect.position.y = sd->descent;
|
||||
} break;
|
||||
}
|
||||
switch (E.value.inline_align & INLINE_ALIGNMENT_IMAGE_MASK) {
|
||||
case INLINE_ALIGNMENT_BOTTOM_TO: {
|
||||
E.value.rect.position.y -= E.value.rect.size.y;
|
||||
} break;
|
||||
case INLINE_ALIGNMENT_CENTER_TO: {
|
||||
E.value.rect.position.y -= E.value.rect.size.y / 2;
|
||||
} break;
|
||||
case INLINE_ALIGNMENT_TOP_TO: {
|
||||
// NOP
|
||||
} break;
|
||||
}
|
||||
full_ascent = MAX(full_ascent, -E.value.rect.position.y);
|
||||
full_descent = MAX(full_descent, E.value.rect.position.y + E.value.rect.size.y);
|
||||
} else {
|
||||
switch (E.value.inline_align & INLINE_ALIGNMENT_TEXT_MASK) {
|
||||
case INLINE_ALIGNMENT_TO_TOP: {
|
||||
E.value.rect.position.x = -sd->ascent;
|
||||
} break;
|
||||
case INLINE_ALIGNMENT_TO_CENTER: {
|
||||
E.value.rect.position.x = (-sd->ascent + sd->descent) / 2;
|
||||
} break;
|
||||
case INLINE_ALIGNMENT_TO_BASELINE: {
|
||||
E.value.rect.position.x = 0;
|
||||
} break;
|
||||
case INLINE_ALIGNMENT_TO_BOTTOM: {
|
||||
E.value.rect.position.x = sd->descent;
|
||||
} break;
|
||||
}
|
||||
switch (E.value.inline_align & INLINE_ALIGNMENT_IMAGE_MASK) {
|
||||
case INLINE_ALIGNMENT_BOTTOM_TO: {
|
||||
E.value.rect.position.x -= E.value.rect.size.x;
|
||||
} break;
|
||||
case INLINE_ALIGNMENT_CENTER_TO: {
|
||||
E.value.rect.position.x -= E.value.rect.size.x / 2;
|
||||
} break;
|
||||
case INLINE_ALIGNMENT_TOP_TO: {
|
||||
// NOP
|
||||
} break;
|
||||
}
|
||||
full_ascent = MAX(full_ascent, -E.value.rect.position.x);
|
||||
full_descent = MAX(full_descent, E.value.rect.position.x + E.value.rect.size.x);
|
||||
}
|
||||
}
|
||||
}
|
||||
sd->ascent = full_ascent;
|
||||
sd->descent = full_descent;
|
||||
_realign(sd);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void TextServerFallback::_realign(ShapedTextDataFallback *p_sd) const {
|
||||
// Align embedded objects to baseline.
|
||||
float full_ascent = p_sd->ascent;
|
||||
float full_descent = p_sd->descent;
|
||||
for (KeyValue<Variant, ShapedTextDataFallback::EmbeddedObject> &E : p_sd->objects) {
|
||||
if ((E.value.pos >= p_sd->start) && (E.value.pos < p_sd->end)) {
|
||||
if (p_sd->orientation == ORIENTATION_HORIZONTAL) {
|
||||
switch (E.value.inline_align & INLINE_ALIGNMENT_TEXT_MASK) {
|
||||
case INLINE_ALIGNMENT_TO_TOP: {
|
||||
E.value.rect.position.y = -p_sd->ascent;
|
||||
} break;
|
||||
case INLINE_ALIGNMENT_TO_CENTER: {
|
||||
E.value.rect.position.y = (-p_sd->ascent + p_sd->descent) / 2;
|
||||
} break;
|
||||
case INLINE_ALIGNMENT_TO_BASELINE: {
|
||||
E.value.rect.position.y = 0;
|
||||
} break;
|
||||
case INLINE_ALIGNMENT_TO_BOTTOM: {
|
||||
E.value.rect.position.y = p_sd->descent;
|
||||
} break;
|
||||
}
|
||||
switch (E.value.inline_align & INLINE_ALIGNMENT_IMAGE_MASK) {
|
||||
case INLINE_ALIGNMENT_BOTTOM_TO: {
|
||||
E.value.rect.position.y -= E.value.rect.size.y;
|
||||
} break;
|
||||
case INLINE_ALIGNMENT_CENTER_TO: {
|
||||
E.value.rect.position.y -= E.value.rect.size.y / 2;
|
||||
} break;
|
||||
case INLINE_ALIGNMENT_TOP_TO: {
|
||||
// NOP
|
||||
} break;
|
||||
}
|
||||
full_ascent = MAX(full_ascent, -E.value.rect.position.y);
|
||||
full_descent = MAX(full_descent, E.value.rect.position.y + E.value.rect.size.y);
|
||||
} else {
|
||||
switch (E.value.inline_align & INLINE_ALIGNMENT_TEXT_MASK) {
|
||||
case INLINE_ALIGNMENT_TO_TOP: {
|
||||
E.value.rect.position.x = -p_sd->ascent;
|
||||
} break;
|
||||
case INLINE_ALIGNMENT_TO_CENTER: {
|
||||
E.value.rect.position.x = (-p_sd->ascent + p_sd->descent) / 2;
|
||||
} break;
|
||||
case INLINE_ALIGNMENT_TO_BASELINE: {
|
||||
E.value.rect.position.x = 0;
|
||||
} break;
|
||||
case INLINE_ALIGNMENT_TO_BOTTOM: {
|
||||
E.value.rect.position.x = p_sd->descent;
|
||||
} break;
|
||||
}
|
||||
switch (E.value.inline_align & INLINE_ALIGNMENT_IMAGE_MASK) {
|
||||
case INLINE_ALIGNMENT_BOTTOM_TO: {
|
||||
E.value.rect.position.x -= E.value.rect.size.x;
|
||||
} break;
|
||||
case INLINE_ALIGNMENT_CENTER_TO: {
|
||||
E.value.rect.position.x -= E.value.rect.size.x / 2;
|
||||
} break;
|
||||
case INLINE_ALIGNMENT_TOP_TO: {
|
||||
// NOP
|
||||
} break;
|
||||
}
|
||||
full_ascent = MAX(full_ascent, -E.value.rect.position.x);
|
||||
full_descent = MAX(full_descent, E.value.rect.position.x + E.value.rect.size.x);
|
||||
}
|
||||
}
|
||||
}
|
||||
p_sd->ascent = full_ascent;
|
||||
p_sd->descent = full_descent;
|
||||
}
|
||||
|
||||
RID TextServerFallback::shaped_text_substr(RID p_shaped, int p_start, int p_length) const {
|
||||
const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
const ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V(!sd, RID());
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
@@ -2450,7 +2491,7 @@ RID TextServerFallback::shaped_text_substr(RID p_shaped, int p_start, int p_leng
|
||||
ERR_FAIL_COND_V(sd->start > p_start || sd->end < p_start, RID());
|
||||
ERR_FAIL_COND_V(sd->end < p_start + p_length, RID());
|
||||
|
||||
ShapedTextData *new_sd = memnew(ShapedTextData);
|
||||
ShapedTextDataFallback *new_sd = memnew(ShapedTextDataFallback);
|
||||
new_sd->parent = p_shaped;
|
||||
new_sd->start = p_start;
|
||||
new_sd->end = p_start + p_length;
|
||||
@@ -2476,7 +2517,7 @@ RID TextServerFallback::shaped_text_substr(RID p_shaped, int p_start, int p_leng
|
||||
Variant key;
|
||||
bool find_embedded = false;
|
||||
if (gl.count == 1) {
|
||||
for (const KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : sd->objects) {
|
||||
for (const KeyValue<Variant, ShapedTextDataFallback::EmbeddedObject> &E : sd->objects) {
|
||||
if (E.value.pos == gl.start) {
|
||||
find_embedded = true;
|
||||
key = E.key;
|
||||
@@ -2520,7 +2561,7 @@ RID TextServerFallback::shaped_text_substr(RID p_shaped, int p_start, int p_leng
|
||||
// Align embedded objects to baseline.
|
||||
float full_ascent = new_sd->ascent;
|
||||
float full_descent = new_sd->descent;
|
||||
for (KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : new_sd->objects) {
|
||||
for (KeyValue<Variant, ShapedTextDataFallback::EmbeddedObject> &E : new_sd->objects) {
|
||||
if ((E.value.pos >= new_sd->start) && (E.value.pos < new_sd->end)) {
|
||||
if (sd->orientation == ORIENTATION_HORIZONTAL) {
|
||||
switch (E.value.inline_align & INLINE_ALIGNMENT_TEXT_MASK) {
|
||||
@@ -2590,7 +2631,7 @@ RID TextServerFallback::shaped_text_substr(RID p_shaped, int p_start, int p_leng
|
||||
}
|
||||
|
||||
RID TextServerFallback::shaped_text_get_parent(RID p_shaped) const {
|
||||
ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V(!sd, RID());
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
@@ -2598,7 +2639,7 @@ RID TextServerFallback::shaped_text_get_parent(RID p_shaped) const {
|
||||
}
|
||||
|
||||
float TextServerFallback::shaped_text_fit_to_width(RID p_shaped, float p_width, uint16_t /*JustificationFlag*/ p_jst_flags) {
|
||||
ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V(!sd, 0.f);
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
@@ -2707,7 +2748,7 @@ float TextServerFallback::shaped_text_fit_to_width(RID p_shaped, float p_width,
|
||||
}
|
||||
|
||||
float TextServerFallback::shaped_text_tab_align(RID p_shaped, const PackedFloat32Array &p_tab_stops) {
|
||||
ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V(!sd, 0.f);
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
@@ -2763,7 +2804,7 @@ float TextServerFallback::shaped_text_tab_align(RID p_shaped, const PackedFloat3
|
||||
}
|
||||
|
||||
bool TextServerFallback::shaped_text_update_breaks(RID p_shaped) {
|
||||
ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V(!sd, false);
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
@@ -2819,7 +2860,7 @@ bool TextServerFallback::shaped_text_update_breaks(RID p_shaped) {
|
||||
}
|
||||
|
||||
bool TextServerFallback::shaped_text_update_justification_ops(RID p_shaped) {
|
||||
ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V(!sd, false);
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
@@ -2835,7 +2876,7 @@ bool TextServerFallback::shaped_text_update_justification_ops(RID p_shaped) {
|
||||
}
|
||||
|
||||
void TextServerFallback::shaped_text_overrun_trim_to_width(RID p_shaped_line, float p_width, uint16_t p_trim_flags) {
|
||||
ShapedTextData *sd = shaped_owner.get_or_null(p_shaped_line);
|
||||
ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped_line);
|
||||
ERR_FAIL_COND_MSG(!sd, "ShapedTextDataFallback invalid.");
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
@@ -2863,9 +2904,9 @@ void TextServerFallback::shaped_text_overrun_trim_to_width(RID p_shaped_line, fl
|
||||
return;
|
||||
}
|
||||
|
||||
Vector<ShapedTextData::Span> &spans = sd->spans;
|
||||
Vector<ShapedTextDataFallback::Span> &spans = sd->spans;
|
||||
if (sd->parent != RID()) {
|
||||
ShapedTextData *parent_sd = shaped_owner.get_or_null(sd->parent);
|
||||
ShapedTextDataFallback *parent_sd = shaped_owner.get_or_null(sd->parent);
|
||||
ERR_FAIL_COND(!parent_sd->valid);
|
||||
spans = parent_sd->spans;
|
||||
}
|
||||
@@ -2987,39 +3028,39 @@ void TextServerFallback::shaped_text_overrun_trim_to_width(RID p_shaped_line, fl
|
||||
}
|
||||
|
||||
int TextServerFallback::shaped_text_get_trim_pos(RID p_shaped) const {
|
||||
ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V_MSG(!sd, -1, "ShapedTextData invalid.");
|
||||
ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V_MSG(!sd, -1, "ShapedTextDataFallback invalid.");
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
return sd->overrun_trim_data.trim_pos;
|
||||
}
|
||||
|
||||
int TextServerFallback::shaped_text_get_ellipsis_pos(RID p_shaped) const {
|
||||
ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V_MSG(!sd, -1, "ShapedTextData invalid.");
|
||||
ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V_MSG(!sd, -1, "ShapedTextDataFallback invalid.");
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
return sd->overrun_trim_data.ellipsis_pos;
|
||||
}
|
||||
|
||||
const Glyph *TextServerFallback::shaped_text_get_ellipsis_glyphs(RID p_shaped) const {
|
||||
ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V_MSG(!sd, nullptr, "ShapedTextData invalid.");
|
||||
ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V_MSG(!sd, nullptr, "ShapedTextDataFallback invalid.");
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
return sd->overrun_trim_data.ellipsis_glyph_buf.ptr();
|
||||
}
|
||||
|
||||
int TextServerFallback::shaped_text_get_ellipsis_glyph_count(RID p_shaped) const {
|
||||
ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V_MSG(!sd, 0, "ShapedTextData invalid.");
|
||||
ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V_MSG(!sd, 0, "ShapedTextDataFallback invalid.");
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
return sd->overrun_trim_data.ellipsis_glyph_buf.size();
|
||||
}
|
||||
|
||||
bool TextServerFallback::shaped_text_shape(RID p_shaped) {
|
||||
ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V(!sd, false);
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
@@ -3046,7 +3087,7 @@ bool TextServerFallback::shaped_text_shape(RID p_shaped) {
|
||||
|
||||
// "Shape" string.
|
||||
for (int i = 0; i < sd->spans.size(); i++) {
|
||||
const ShapedTextData::Span &span = sd->spans[i];
|
||||
const ShapedTextDataFallback::Span &span = sd->spans[i];
|
||||
if (span.embedded_key != Variant()) {
|
||||
// Embedded object.
|
||||
if (sd->orientation == ORIENTATION_HORIZONTAL) {
|
||||
@@ -3146,7 +3187,7 @@ bool TextServerFallback::shaped_text_shape(RID p_shaped) {
|
||||
// Align embedded objects to baseline.
|
||||
float full_ascent = sd->ascent;
|
||||
float full_descent = sd->descent;
|
||||
for (KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : sd->objects) {
|
||||
for (KeyValue<Variant, ShapedTextDataFallback::EmbeddedObject> &E : sd->objects) {
|
||||
if (sd->orientation == ORIENTATION_HORIZONTAL) {
|
||||
switch (E.value.inline_align & INLINE_ALIGNMENT_TEXT_MASK) {
|
||||
case INLINE_ALIGNMENT_TO_TOP: {
|
||||
@@ -3212,7 +3253,7 @@ bool TextServerFallback::shaped_text_shape(RID p_shaped) {
|
||||
}
|
||||
|
||||
bool TextServerFallback::shaped_text_is_ready(RID p_shaped) const {
|
||||
const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
const ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V(!sd, false);
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
@@ -3220,7 +3261,7 @@ bool TextServerFallback::shaped_text_is_ready(RID p_shaped) const {
|
||||
}
|
||||
|
||||
const Glyph *TextServerFallback::shaped_text_get_glyphs(RID p_shaped) const {
|
||||
const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
const ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V(!sd, nullptr);
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
@@ -3231,7 +3272,7 @@ const Glyph *TextServerFallback::shaped_text_get_glyphs(RID p_shaped) const {
|
||||
}
|
||||
|
||||
int TextServerFallback::shaped_text_get_glyph_count(RID p_shaped) const {
|
||||
const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
const ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V(!sd, 0);
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
@@ -3242,7 +3283,7 @@ int TextServerFallback::shaped_text_get_glyph_count(RID p_shaped) const {
|
||||
}
|
||||
|
||||
const Glyph *TextServerFallback::shaped_text_sort_logical(RID p_shaped) {
|
||||
const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
const ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V(!sd, nullptr);
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
@@ -3254,7 +3295,7 @@ const Glyph *TextServerFallback::shaped_text_sort_logical(RID p_shaped) {
|
||||
}
|
||||
|
||||
Vector2i TextServerFallback::shaped_text_get_range(RID p_shaped) const {
|
||||
const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
const ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V(!sd, Vector2i());
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
@@ -3263,11 +3304,11 @@ Vector2i TextServerFallback::shaped_text_get_range(RID p_shaped) const {
|
||||
|
||||
Array TextServerFallback::shaped_text_get_objects(RID p_shaped) const {
|
||||
Array ret;
|
||||
const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
const ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V(!sd, ret);
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
for (const KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : sd->objects) {
|
||||
for (const KeyValue<Variant, ShapedTextDataFallback::EmbeddedObject> &E : sd->objects) {
|
||||
ret.push_back(E.key);
|
||||
}
|
||||
|
||||
@@ -3275,7 +3316,7 @@ Array TextServerFallback::shaped_text_get_objects(RID p_shaped) const {
|
||||
}
|
||||
|
||||
Rect2 TextServerFallback::shaped_text_get_object_rect(RID p_shaped, Variant p_key) const {
|
||||
const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
const ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V(!sd, Rect2());
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
@@ -3287,7 +3328,7 @@ Rect2 TextServerFallback::shaped_text_get_object_rect(RID p_shaped, Variant p_ke
|
||||
}
|
||||
|
||||
Size2 TextServerFallback::shaped_text_get_size(RID p_shaped) const {
|
||||
const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
const ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V(!sd, Size2());
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
@@ -3302,7 +3343,7 @@ Size2 TextServerFallback::shaped_text_get_size(RID p_shaped) const {
|
||||
}
|
||||
|
||||
float TextServerFallback::shaped_text_get_ascent(RID p_shaped) const {
|
||||
const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
const ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V(!sd, 0.f);
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
@@ -3313,7 +3354,7 @@ float TextServerFallback::shaped_text_get_ascent(RID p_shaped) const {
|
||||
}
|
||||
|
||||
float TextServerFallback::shaped_text_get_descent(RID p_shaped) const {
|
||||
const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
const ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V(!sd, 0.f);
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
@@ -3324,7 +3365,7 @@ float TextServerFallback::shaped_text_get_descent(RID p_shaped) const {
|
||||
}
|
||||
|
||||
float TextServerFallback::shaped_text_get_width(RID p_shaped) const {
|
||||
const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
const ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V(!sd, 0.f);
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
@@ -3335,7 +3376,7 @@ float TextServerFallback::shaped_text_get_width(RID p_shaped) const {
|
||||
}
|
||||
|
||||
float TextServerFallback::shaped_text_get_underline_position(RID p_shaped) const {
|
||||
const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
const ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V(!sd, 0.f);
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
@@ -3347,7 +3388,7 @@ float TextServerFallback::shaped_text_get_underline_position(RID p_shaped) const
|
||||
}
|
||||
|
||||
float TextServerFallback::shaped_text_get_underline_thickness(RID p_shaped) const {
|
||||
const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
|
||||
const ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
|
||||
ERR_FAIL_COND_V(!sd, 0.f);
|
||||
|
||||
MutexLock lock(sd->mutex);
|
||||
|
||||
Reference in New Issue
Block a user