ReactOS 0.4.17-dev-923-g4c9a150
layout.c
Go to the documentation of this file.
1/*
2 * Copyright 2012, 2014-2022 Nikolay Sivov for CodeWeavers
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19#define COBJMACROS
20
21#include <assert.h>
22#include <stdarg.h>
23#include <math.h>
24
25#include "windef.h"
26#include "winbase.h"
27#include "wingdi.h"
28#include "dwrite_private.h"
29#include "scripts.h"
30
32
48};
49
52 union {
63 const WCHAR *locale;
65 struct {
71 } u;
72};
73
81};
82
84 struct list entry;
87};
88
100};
101
105};
106
110};
111
117};
118
123
127};
128
137 UINT32 glyphcount; /* actual glyph count after shaping, not necessarily the same as reported to Draw() */
138};
139
141{
142 struct list entry;
144 union
145 {
148 } u;
149 float baseline;
150 float height;
151 unsigned int start_position; /* run text position in range [0, layout-text-length) */
152};
153
155 struct list entry;
156 const struct layout_run *run; /* nominal run this one is based on */
157 UINT32 start; /* relative text position, 0 means first text position of a nominal run */
158 UINT32 length; /* length in codepoints that this run covers */
159 UINT32 glyphcount; /* total glyph count in this run */
160 IUnknown *effect; /* original reference is kept only at range level */
161 D2D1_POINT_2F origin; /* baseline origin */
162 FLOAT align_dx; /* adjustment from text alignment */
163 FLOAT width; /* run width */
164 UINT16 *clustermap; /* effective clustermap, allocated separately, is not reused from nominal map */
165 UINT32 line; /* 0-based line index in line metrics array */
166 BOOL underlined; /* set if this run is underlined */
167 D2D1_RECT_F bbox; /* ink run box, top == bottom means it wasn't estimated yet */
168};
169
171 struct list entry;
172 IDWriteInlineObject *object; /* inline object, set explicitly or added when trimming a line */
173 IUnknown *effect; /* original reference is kept only at range level */
175 D2D1_POINT_2F origin; /* left top corner */
176 FLOAT align_dx; /* adjustment from text alignment */
177 FLOAT width; /* object width as it's reported it */
178 BOOL is_sideways; /* vertical flow direction flag passed to Draw */
179 BOOL is_rtl; /* bidi flag passed to Draw */
180 UINT32 line; /* 0-based line index in line metrics array */
181};
182
184 struct list entry;
187};
188
190 struct list entry;
193};
194
196 const struct layout_run *run; /* link to nominal run this cluster belongs to */
197 UINT32 position; /* relative to run, first cluster has 0 position */
198};
199
201{
202 float height; /* height based on content */
203 float baseline; /* baseline based on content */
205};
206
213 RECOMPUTE_EVERYTHING = 0xffff
215
217{
223
226
229
230 struct
231 {
232 unsigned int offset;
233 unsigned int length;
235
240 struct list effects;
241 struct list spacing;
242 struct list ranges;
243 struct list runs;
244 /* lists ready to use by Draw() */
245 struct list eruns;
250
253
258
261
264
266
267 /* gdi-compatible layout specifics */
270};
271
275
277 size_t capacity;
278 size_t count;
279};
280
282{
284}
285
287{
289}
290
292{
294}
295
297{
299}
300
302{
304}
305
306static inline const char *debugstr_rundescr(const DWRITE_GLYPH_RUN_DESCRIPTION *descr)
307{
308 return wine_dbg_sprintf("[%u,%u)", descr->textPosition, descr->textPosition + descr->stringLength);
309}
310
311static inline BOOL is_layout_gdi_compatible(const struct dwrite_textlayout *layout)
312{
314}
315
316static BOOL is_run_rtl(const struct layout_effective_run *run)
317{
318 return run->run->u.regular.run.bidiLevel & 1;
319}
320
321static HRESULT alloc_layout_run(enum layout_run_kind kind, unsigned int start_position,
322 struct layout_run **run)
323{
324 if (!(*run = calloc(1, sizeof(**run))))
325 return E_OUTOFMEMORY;
326
327 (*run)->kind = kind;
328 (*run)->start_position = start_position;
329
330 return S_OK;
331}
332
333static void free_layout_runs(struct dwrite_textlayout *layout)
334{
335 struct layout_run *cur, *cur2;
336 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &layout->runs, struct layout_run, entry)
337 {
338 list_remove(&cur->entry);
339 if (cur->kind == LAYOUT_RUN_REGULAR)
340 {
341 if (cur->u.regular.run.fontFace)
342 IDWriteFontFace_Release(cur->u.regular.run.fontFace);
343 free(cur->u.regular.glyphs);
344 free(cur->u.regular.clustermap);
345 free(cur->u.regular.advances);
346 free(cur->u.regular.offsets);
347 }
348 free(cur);
349 }
350}
351
352static void free_layout_eruns(struct dwrite_textlayout *layout)
353{
354 struct layout_effective_inline *in, *in2;
355 struct layout_effective_run *cur, *cur2;
356 struct layout_strikethrough *s, *s2;
357 struct layout_underline *u, *u2;
358
360 {
361 list_remove(&cur->entry);
362 free(cur->clustermap);
363 free(cur);
364 }
365
367 {
368 list_remove(&in->entry);
369 free(in);
370 }
371
373 {
374 list_remove(&u->entry);
375 free(u);
376 }
377
379 {
380 list_remove(&s->entry);
381 free(s);
382 }
383}
384
385/* Used to resolve break condition by forcing stronger condition over weaker. */
387{
388 switch (existingbreak) {
390 return newbreak;
392 return newbreak == DWRITE_BREAK_CONDITION_NEUTRAL ? existingbreak : newbreak;
393 /* let's keep stronger conditions as is */
396 break;
397 default:
398 ERR("unknown break condition %d\n", existingbreak);
399 }
400
401 return existingbreak;
402}
403
404/* This helper should be used to get effective range length, in other words it returns number of text
405 positions from range starting point to the end of the range, limited by layout text length */
406static inline UINT32 get_clipped_range_length(const struct dwrite_textlayout *layout, const struct layout_range *range)
407{
408 if (range->h.range.startPosition + range->h.range.length <= layout->len)
409 return range->h.range.length;
410 return layout->len - range->h.range.startPosition;
411}
412
413/* Actual breakpoint data gets updated with break condition required by inline object set for range 'cur'. */
415{
417 UINT32 i, length;
418 HRESULT hr;
419
420 /* ignore returned conditions if failed */
421 hr = IDWriteInlineObject_GetBreakConditions(cur->object, &before, &after);
422 if (FAILED(hr))
424
425 if (!layout->actual_breakpoints)
426 {
427 if (!(layout->actual_breakpoints = calloc(layout->len, sizeof(*layout->actual_breakpoints))))
428 return E_OUTOFMEMORY;
430 }
431
433 for (i = cur->h.range.startPosition; i < length + cur->h.range.startPosition; i++) {
434 /* for first codepoint check if there's anything before it and update accordingly */
435 if (i == cur->h.range.startPosition) {
436 if (i > 0)
439 else
442 }
443 /* similar check for last codepoint */
444 else if (i == cur->h.range.startPosition + length - 1) {
445 if (i == layout->len - 1)
447 else
451 }
452 /* for all positions within a range disable breaks */
453 else {
456 }
457
458 layout->actual_breakpoints[i].isWhitespace = 0;
459 layout->actual_breakpoints[i].isSoftHyphen = 0;
460 }
461
462 return S_OK;
463}
464
466{
467 struct layout_range *cur;
468
469 LIST_FOR_EACH_ENTRY(cur, &layout->ranges, struct layout_range, h.entry)
470 {
471 DWRITE_TEXT_RANGE *r = &cur->h.range;
472 if (r->startPosition <= pos && pos < r->startPosition + r->length)
473 return cur;
474 }
475
476 return NULL;
477}
478
480{
481 struct layout_range_header *cur;
482
484 {
485 DWRITE_TEXT_RANGE *r = &cur->range;
486 if (r->startPosition <= pos && pos < r->startPosition + r->length)
487 return cur;
488 }
489
490 return NULL;
491}
492
494{
495 if (layout->actual_breakpoints)
496 return layout->actual_breakpoints[pos];
497 return layout->nominal_breakpoints[pos];
498}
499
500static inline void init_cluster_metrics(const struct dwrite_textlayout *layout, const struct regular_layout_run *run,
501 UINT16 start_glyph, UINT16 stop_glyph, UINT32 stop_position, UINT16 length, DWRITE_CLUSTER_METRICS *metrics)
502{
503 UINT8 breakcondition;
504 UINT32 position;
505 UINT16 j;
506
507 /* For clusters made of control chars we report zero glyphs, and we need zero cluster
508 width as well; advances are already computed at this point and are not necessary zero. */
509 metrics->width = 0.0f;
510 if (run->run.glyphCount) {
511 for (j = start_glyph; j < stop_glyph; j++)
512 metrics->width += run->run.glyphAdvances[j];
513 }
514 metrics->length = length;
515
516 position = run->descr.textPosition + stop_position;
517 if (stop_glyph == run->glyphcount)
518 breakcondition = get_effective_breakpoint(layout, position).breakConditionAfter;
519 else {
520 breakcondition = get_effective_breakpoint(layout, position).breakConditionBefore;
521 if (stop_position) position -= 1;
522 }
523
524 metrics->canWrapLineAfter = breakcondition == DWRITE_BREAK_CONDITION_CAN_BREAK ||
525 breakcondition == DWRITE_BREAK_CONDITION_MUST_BREAK;
526 if (metrics->length == 1) {
528 metrics->isWhitespace = bp.isWhitespace;
529 metrics->isNewline = metrics->canWrapLineAfter && lb_is_newline_char(layout->str[position]);
530 metrics->isSoftHyphen = bp.isSoftHyphen;
531 }
532 else {
533 metrics->isWhitespace = 0;
534 metrics->isNewline = 0;
535 metrics->isSoftHyphen = 0;
536 }
537 metrics->isRightToLeft = run->run.bidiLevel & 1;
538 metrics->padding = 0;
539}
540
541/*
542
543 All clusters in a 'run' will be added to 'layout' data, starting at index pointed to by 'cluster'.
544 On return 'cluster' is updated to point to next metrics struct to be filled in on next call.
545 Note that there's no need to reallocate anything at this point as we allocate one cluster per
546 codepoint initially.
547
548*/
549static void layout_set_cluster_metrics(struct dwrite_textlayout *layout, const struct layout_run *r, UINT32 *cluster)
550{
551 DWRITE_CLUSTER_METRICS *metrics = &layout->clustermetrics[*cluster];
552 struct layout_cluster *c = &layout->clusters[*cluster];
553 const struct regular_layout_run *run = &r->u.regular;
554 UINT32 i, start = 0;
555
556 assert(r->kind == LAYOUT_RUN_REGULAR);
557
558 for (i = 0; i < run->descr.stringLength; i++) {
559 BOOL end = i == run->descr.stringLength - 1;
560
561 if (run->descr.clusterMap[start] != run->descr.clusterMap[i]) {
562 init_cluster_metrics(layout, run, run->descr.clusterMap[start], run->descr.clusterMap[i], i,
563 i - start, metrics);
564 c->position = start;
565 c->run = r;
566
567 *cluster += 1;
568 metrics++;
569 c++;
570 start = i;
571 }
572
573 if (end) {
574 init_cluster_metrics(layout, run, run->descr.clusterMap[start], run->glyphcount, i,
575 i - start + 1, metrics);
576 c->position = start;
577 c->run = r;
578
579 *cluster += 1;
580 return;
581 }
582 }
583}
584
585#define SCALE_FONT_METRIC(metric, emSize, metrics) ((FLOAT)(metric) * (emSize) / (FLOAT)(metrics)->designUnitsPerEm)
586
587static void layout_get_font_metrics(const struct dwrite_textlayout *layout, IDWriteFontFace *fontface, float emsize,
588 DWRITE_FONT_METRICS *fontmetrics)
589{
590 if (is_layout_gdi_compatible(layout)) {
591 HRESULT hr = IDWriteFontFace_GetGdiCompatibleMetrics(fontface, emsize, layout->ppdip, &layout->transform, fontmetrics);
592 if (FAILED(hr))
593 WARN("failed to get compat metrics, 0x%08lx\n", hr);
594 }
595 else
596 IDWriteFontFace_GetMetrics(fontface, fontmetrics);
597}
598
599static inline void layout_get_font_height(float emsize, const DWRITE_FONT_METRICS *fontmetrics, float *baseline, float *height)
600{
601 *baseline = SCALE_FONT_METRIC(fontmetrics->ascent + fontmetrics->lineGap, emsize, fontmetrics);
602 *height = SCALE_FONT_METRIC(fontmetrics->ascent + fontmetrics->descent + fontmetrics->lineGap, emsize, fontmetrics);
603}
604
605static inline void layout_initialize_text_source(struct dwrite_textlayout *layout, unsigned int offset,
606 unsigned int length)
607{
608 layout->text_source.offset = offset;
609 layout->text_source.length = length;
610}
611
613{
614 IDWriteTextAnalyzer2 *analyzer;
615 struct layout_range *range;
616 struct layout_run *r;
617 HRESULT hr = S_OK;
618
619 analyzer = get_text_analyzer();
620
621 layout_initialize_text_source(layout, 0, layout->len);
622 LIST_FOR_EACH_ENTRY(range, &layout->ranges, struct layout_range, h.entry) {
623 /* We don't care about ranges that don't contain any text. */
624 if (range->h.range.startPosition >= layout->len)
625 break;
626
627 /* Inline objects override actual text in range. */
628 if (range->object) {
630 if (FAILED(hr))
631 return hr;
632
633 if (FAILED(hr = alloc_layout_run(LAYOUT_RUN_INLINE, range->h.range.startPosition, &r)))
634 return hr;
635
636 r->u.object.object = range->object;
637 r->u.object.length = get_clipped_range_length(layout, range);
638 list_add_tail(&layout->runs, &r->entry);
639 continue;
640 }
641
642 /* Initial splitting by script. */
643 hr = IDWriteTextAnalyzer2_AnalyzeScript(analyzer, (IDWriteTextAnalysisSource *)&layout->IDWriteTextAnalysisSource1_iface,
644 range->h.range.startPosition, get_clipped_range_length(layout, range),
646 if (FAILED(hr))
647 break;
648
649 /* Splitting further by bidi levels. */
650 hr = IDWriteTextAnalyzer2_AnalyzeBidi(analyzer, (IDWriteTextAnalysisSource *)&layout->IDWriteTextAnalysisSource1_iface,
651 range->h.range.startPosition, get_clipped_range_length(layout, range),
653 if (FAILED(hr))
654 break;
655 }
656
657 return hr;
658}
659
661 IDWriteFontFallback *fallback, struct layout_run **remaining)
662{
663 struct regular_layout_run *run = &r->u.regular;
665 struct layout_range *range;
666 unsigned int length;
667 HRESULT hr = S_OK;
668
669 *remaining = NULL;
670
672 collection = range->collection ? range->collection : layout->system_collection;
673
675
676 while (length)
677 {
678 unsigned int mapped_length = 0;
680 float scale = 0.0f;
681
682 run = &r->u.regular;
683
685 hr = IDWriteFontFallback_MapCharacters(fallback, (IDWriteTextAnalysisSource *)&layout->IDWriteTextAnalysisSource1_iface,
686 0, run->descr.stringLength, collection, range->fontfamily, range->weight, range->style, range->stretch,
687 &mapped_length, &font, &scale);
688 if (FAILED(hr))
689 {
690 WARN("%s: failed to map family %s, collection %p, hr %#lx.\n", debugstr_rundescr(&run->descr),
691 debugstr_w(range->fontfamily), collection, hr);
692 return hr;
693 }
694
695 if (!font)
696 {
697 *remaining = r;
698 return S_OK;
699 }
700
701 hr = IDWriteFont_CreateFontFace(font, &run->run.fontFace);
702 IDWriteFont_Release(font);
703 if (FAILED(hr))
704 {
705 WARN("Failed to create a font face, hr %#lx.\n", hr);
706 return hr;
707 }
708
709 run->run.fontEmSize = range->fontsize * scale;
710
711 if (mapped_length < length)
712 {
713 struct regular_layout_run *nextrun;
714 struct layout_run *nextr;
715
716 /* Keep mapped part for current run, add another run for the rest. */
717 if (FAILED(hr = alloc_layout_run(LAYOUT_RUN_REGULAR, 0, &nextr)))
718 return hr;
719
720 *nextr = *r;
721 nextr->start_position = run->descr.textPosition + mapped_length;
722 nextrun = &nextr->u.regular;
723 nextrun->run.fontFace = NULL;
724 nextrun->descr.textPosition = nextr->start_position;
725 nextrun->descr.stringLength = run->descr.stringLength - mapped_length;
726 nextrun->descr.string = &layout->str[nextrun->descr.textPosition];
727 run->descr.stringLength = mapped_length;
728 list_add_after(&r->entry, &nextr->entry);
729 r = nextr;
730 }
731
732 length -= min(length, mapped_length);
733 }
734
735 return hr;
736}
737
739 IDWriteFontFace **fontface, float *size)
740{
742 HRESULT hr;
743
744 if (FAILED(create_matching_font(range->collection, range->fontfamily, range->weight, range->style,
745 range->stretch, &IID_IDWriteFont3, (void **)&font)))
746 {
747 if (FAILED(hr = create_matching_font(layout->system_collection, L"Tahoma", range->weight, range->style,
748 range->stretch, &IID_IDWriteFont3, (void **)&font)))
749 {
750 WARN("Failed to create last resort font, hr %#lx.\n", hr);
751 return hr;
752 }
753 }
754
755 hr = IDWriteFont_CreateFontFace(font, fontface);
756 IDWriteFont_Release(font);
757 if (FAILED(hr))
758 {
759 WARN("Failed to create last resort font face, hr %#lx.\n", hr);
760 return hr;
761 }
762
763 *size = range->fontsize;
764
765 return hr;
766}
767
769{
771 struct layout_run *r, *remaining;
772 HRESULT hr;
773
774 if (FAILED(hr = IDWriteFactory7_GetSystemFontFallback(layout->factory, &system_fallback)))
775 {
776 WARN("Failed to get system fallback, hr %#lx.\n", hr);
777 return hr;
778 }
779
780 LIST_FOR_EACH_ENTRY(r, &layout->runs, struct layout_run, entry)
781 {
782 struct regular_layout_run *run = &r->u.regular;
783
784 if (r->kind == LAYOUT_RUN_INLINE)
785 continue;
786
787 /* For textual runs use both custom and system fallback. For non-visual ones only use the system fallback,
788 and no hard-coded names in assumption that support for missing control characters could be easily
789 added to bundled fonts. */
790
791 if (run->sa.shapes == DWRITE_SCRIPT_SHAPES_NO_VISUAL)
792 {
793 if (FAILED(hr = layout_map_run_characters(layout, r, system_fallback, &remaining)))
794 {
795 WARN("Failed to map fonts for non-visual run, hr %#lx.\n", hr);
796 break;
797 }
798 }
799 else
800 {
801 if (layout->format.fallback)
802 hr = layout_map_run_characters(layout, r, layout->format.fallback, &remaining);
803 else
804 remaining = r;
805
806 if (remaining)
807 hr = layout_map_run_characters(layout, remaining, system_fallback, &remaining);
808 }
809
810 if (remaining)
811 {
812 hr = layout_run_get_last_resort_font(layout, get_layout_range_by_pos(layout, remaining->u.regular.descr.textPosition),
813 &remaining->u.regular.run.fontFace, &remaining->u.regular.run.fontEmSize);
814 }
815
816 if (FAILED(hr)) break;
817 }
818
819 IDWriteFontFallback_Release(system_fallback);
820
821 return hr;
822}
823
825{
830
831 struct
832 {
834 unsigned int *range_lengths;
835 unsigned int range_count;
837};
838
840{
841 unsigned int i;
842
843 for (i = 0; i < context->user_features.range_count; ++i)
844 {
845 free(context->user_features.features[i]->features);
846 free(context->user_features.features[i]);
847 }
848 free(context->user_features.features);
849 memset(&context->user_features, 0, sizeof(context->user_features));
850}
851
853{
855 free(context->glyph_props);
856 free(context->text_props);
857}
858
860{
862 unsigned int r = context->user_features.range_count;
863
864 if (!(context->user_features.features[r] = calloc(1, sizeof(*features))))
865 return E_OUTOFMEMORY;
866
867 context->user_features.range_lengths[r] = length;
868 context->user_features.range_count++;
869
870 return S_OK;
871}
872
874{
875 unsigned int i, f, start = 0, r, covered_length = 0, length, feature_count;
876 struct regular_layout_run *run = context->run;
879 IDWriteTypography *typography;
881
883 if (range->h.range.length >= run->descr.stringLength && !range->iface)
884 return S_OK;
885
886 if (!(context->user_features.features = calloc(run->descr.stringLength, sizeof(*context->user_features.features))))
887 goto failed;
888 if (!(context->user_features.range_lengths = calloc(run->descr.stringLength, sizeof(*context->user_features.range_lengths))))
889 goto failed;
890
891 for (i = run->descr.textPosition; i < run->descr.textPosition + run->descr.stringLength; ++i)
892 {
894 if (!range || !range->iface) continue;
895
896 typography = (IDWriteTypography *)range->iface;
897 feature_count = IDWriteTypography_GetFontFeatureCount(typography);
898 if (!feature_count)
899 {
900 i = range->h.range.startPosition + range->h.range.length;
901 continue;
902 }
903
904 if (start != i)
905 {
907 covered_length += i - start;
908 start += range->h.range.length;
909 }
910
911 r = context->user_features.range_count;
912 if (!(features = context->user_features.features[r] = malloc(sizeof(*features))))
913 goto failed;
914
915 context->user_features.range_lengths[r] = length = min(run->descr.textPosition + run->descr.stringLength,
916 range->h.range.startPosition + range->h.range.length) - i;
917 features->featureCount = feature_count;
918 if (!(features->features = calloc(feature_count, sizeof(*features->features))))
919 goto failed;
920
921 for (f = 0; f < feature_count; ++f)
922 {
923 IDWriteTypography_GetFontFeature(typography, f, &features->features[f]);
924 }
925
926 i += length;
927 covered_length += length;
928 context->user_features.range_count++;
929 }
930
931 if (context->user_features.range_count && covered_length < run->descr.stringLength)
932 {
934 goto failed;
935 }
936
937 hr = S_OK;
938
939failed:
940
941 if (!context->user_features.range_count || FAILED(hr))
943
944 return hr;
945}
946
948{
949 struct regular_layout_run *run = context->run;
950 unsigned int max_count;
951 HRESULT hr;
952
953 run->descr.localeName = get_layout_range_by_pos(layout, run->descr.textPosition)->locale;
954 run->clustermap = calloc(run->descr.stringLength, sizeof(*run->clustermap));
955 if (!run->clustermap)
956 return E_OUTOFMEMORY;
957
958 max_count = 3 * run->descr.stringLength / 2 + 16;
959 run->glyphs = calloc(max_count, sizeof(*run->glyphs));
960 if (!run->glyphs)
961 return E_OUTOFMEMORY;
962
963 context->text_props = calloc(run->descr.stringLength, sizeof(*context->text_props));
964 context->glyph_props = calloc(max_count, sizeof(*context->glyph_props));
965 if (!context->text_props || !context->glyph_props)
966 return E_OUTOFMEMORY;
967
969 return hr;
970
971 for (;;)
972 {
973 hr = IDWriteTextAnalyzer2_GetGlyphs(context->analyzer, run->descr.string, run->descr.stringLength, run->run.fontFace,
974 run->run.isSideways, run->run.bidiLevel & 1, &run->sa, run->descr.localeName, NULL /* FIXME */,
975 (const DWRITE_TYPOGRAPHIC_FEATURES **)context->user_features.features, context->user_features.range_lengths,
976 context->user_features.range_count, max_count, run->clustermap, context->text_props, run->glyphs,
977 context->glyph_props, &run->glyphcount);
979 {
980 free(run->glyphs);
981 free(context->glyph_props);
982
983 max_count *= 2;
984
985 run->glyphs = calloc(max_count, sizeof(*run->glyphs));
986 context->glyph_props = calloc(max_count, sizeof(*context->glyph_props));
987 if (!run->glyphs || !context->glyph_props)
988 {
990 break;
991 }
992
993 continue;
994 }
995
996 break;
997 }
998
999 if (FAILED(hr))
1000 WARN("%s: shaping failed, hr %#lx.\n", debugstr_rundescr(&run->descr), hr);
1001
1002 run->run.glyphIndices = run->glyphs;
1003 run->descr.clusterMap = run->clustermap;
1004
1005 return hr;
1006}
1007
1009 const struct layout_range_spacing *cur)
1010{
1011 return (struct layout_range_spacing *)LIST_ENTRY(list_next(&layout->spacing, &cur->h.entry),
1012 struct layout_range_header, entry);
1013}
1014
1016{
1017 struct regular_layout_run *run = context->run;
1018 struct layout_range_spacing *first = NULL, *last = NULL, *cur;
1019 unsigned int i, length, pos, start, end, g0, glyph_count;
1020 struct layout_range_header *h;
1021 UINT16 *clustermap;
1022
1024 {
1025 if ((h->range.startPosition >= run->descr.textPosition &&
1026 h->range.startPosition <= run->descr.textPosition + run->descr.stringLength) ||
1027 (run->descr.textPosition >= h->range.startPosition &&
1028 run->descr.textPosition <= h->range.startPosition + h->range.length))
1029 {
1030 if (!first) first = last = (struct layout_range_spacing *)h;
1031 }
1032 else if (last) break;
1033 }
1034 if (!first) return S_OK;
1035
1036 if (!(clustermap = calloc(run->descr.stringLength, sizeof(*clustermap))))
1037 return E_OUTOFMEMORY;
1038
1039 pos = run->descr.textPosition;
1040
1041 for (cur = first;; cur = layout_get_next_spacing_range(layout, cur))
1042 {
1043 float leading, trailing;
1044
1045 /* The range current spacing settings apply to. */
1046 start = max(pos, cur->h.range.startPosition);
1047 pos = end = min(pos + run->descr.stringLength, cur->h.range.startPosition + cur->h.range.length);
1048
1049 /* Back to run-relative index. */
1050 start -= run->descr.textPosition;
1051 end -= run->descr.textPosition;
1052
1053 length = end - start;
1054
1055 g0 = run->descr.clusterMap[start];
1056
1057 for (i = 0; i < length; ++i)
1058 clustermap[i] = run->descr.clusterMap[start + i] - run->descr.clusterMap[start];
1059
1060 glyph_count = (end < run->descr.stringLength ? run->descr.clusterMap[end] + 1 : run->glyphcount) - g0;
1061
1062 /* There is no direction argument for spacing interface, we have to swap arguments here to get desired output. */
1063 if (run->run.bidiLevel & 1)
1064 {
1065 leading = cur->trailing;
1066 trailing = cur->leading;
1067 }
1068 else
1069 {
1070 leading = cur->leading;
1071 trailing = cur->trailing;
1072 }
1073 IDWriteTextAnalyzer2_ApplyCharacterSpacing(context->analyzer, leading, trailing, cur->min_advance,
1074 length, glyph_count, clustermap, &run->advances[g0], &run->offsets[g0], &context->glyph_props[g0],
1075 &run->advances[g0], &run->offsets[g0]);
1076
1077 if (cur == last) break;
1078 }
1079
1080 free(clustermap);
1081
1082 return S_OK;
1083}
1084
1086{
1087 struct regular_layout_run *run = context->run;
1088 HRESULT hr;
1089
1090 run->advances = calloc(run->glyphcount, sizeof(*run->advances));
1091 run->offsets = calloc(run->glyphcount, sizeof(*run->offsets));
1092 if (!run->advances || !run->offsets)
1093 return E_OUTOFMEMORY;
1094
1095 /* Get advances and offsets. */
1096 if (is_layout_gdi_compatible(layout))
1097 hr = IDWriteTextAnalyzer2_GetGdiCompatibleGlyphPlacements(context->analyzer, run->descr.string, run->descr.clusterMap,
1098 context->text_props, run->descr.stringLength, run->run.glyphIndices, context->glyph_props, run->glyphcount,
1099 run->run.fontFace, run->run.fontEmSize, layout->ppdip, &layout->transform,
1101 &run->sa, run->descr.localeName, (const DWRITE_TYPOGRAPHIC_FEATURES **)context->user_features.features,
1102 context->user_features.range_lengths, context->user_features.range_count, run->advances, run->offsets);
1103 else
1104 hr = IDWriteTextAnalyzer2_GetGlyphPlacements(context->analyzer, run->descr.string, run->descr.clusterMap,
1105 context->text_props, run->descr.stringLength, run->run.glyphIndices, context->glyph_props, run->glyphcount,
1106 run->run.fontFace, run->run.fontEmSize, run->run.isSideways, run->run.bidiLevel & 1, &run->sa,
1107 run->descr.localeName, (const DWRITE_TYPOGRAPHIC_FEATURES **)context->user_features.features,
1108 context->user_features.range_lengths, context->user_features.range_count, run->advances, run->offsets);
1109
1110 if (FAILED(hr))
1111 {
1112 memset(run->advances, 0, run->glyphcount * sizeof(*run->advances));
1113 memset(run->offsets, 0, run->glyphcount * sizeof(*run->offsets));
1114 WARN("%s: failed to get glyph placement info, hr %#lx.\n", debugstr_rundescr(&run->descr), hr);
1115 }
1116
1117 if (SUCCEEDED(hr))
1119
1120 run->run.glyphAdvances = run->advances;
1121 run->run.glyphOffsets = run->offsets;
1122
1123 return hr;
1124}
1125
1127{
1128 struct shaping_context context = { 0 };
1129 HRESULT hr;
1130
1131 context.analyzer = get_text_analyzer();
1132 context.run = run;
1133
1136
1138
1139 /* Special treatment for runs that don't produce visual output, shaping code adds normal glyphs for them,
1140 with valid cluster map and potentially with non-zero advances; layout code exposes those as zero
1141 width clusters. */
1142 if (run->sa.shapes == DWRITE_SCRIPT_SHAPES_NO_VISUAL)
1143 run->run.glyphCount = 0;
1144 else
1145 run->run.glyphCount = run->glyphcount;
1146
1147 return hr;
1148}
1149
1151{
1152 struct layout_run *r;
1153 UINT32 cluster = 0;
1154 HRESULT hr;
1155
1156 free_layout_eruns(layout);
1157 free_layout_runs(layout);
1158
1159 /* Cluster data arrays are allocated once, assuming one text position per cluster. */
1160 if (!layout->clustermetrics && layout->len)
1161 {
1162 layout->clustermetrics = calloc(layout->len, sizeof(*layout->clustermetrics));
1163 layout->clusters = calloc(layout->len, sizeof(*layout->clusters));
1164 if (!layout->clustermetrics || !layout->clusters)
1165 {
1166 free(layout->clustermetrics);
1167 free(layout->clusters);
1168 return E_OUTOFMEMORY;
1169 }
1170 }
1171 layout->cluster_count = 0;
1172
1173 if (FAILED(hr = layout_itemize(layout))) {
1174 WARN("Itemization failed, hr %#lx.\n", hr);
1175 return hr;
1176 }
1177
1178 if (FAILED(hr = layout_resolve_fonts(layout))) {
1179 WARN("Failed to resolve layout fonts, hr %#lx.\n", hr);
1180 return hr;
1181 }
1182
1183 /* fill run info */
1184 LIST_FOR_EACH_ENTRY(r, &layout->runs, struct layout_run, entry) {
1185 struct regular_layout_run *run = &r->u.regular;
1186 DWRITE_FONT_METRICS fontmetrics = { 0 };
1187
1188 /* we need to do very little in case of inline objects */
1189 if (r->kind == LAYOUT_RUN_INLINE) {
1190 DWRITE_CLUSTER_METRICS *metrics = &layout->clustermetrics[cluster];
1191 struct layout_cluster *c = &layout->clusters[cluster];
1192 DWRITE_INLINE_OBJECT_METRICS inlinemetrics;
1193
1194 metrics->width = 0.0f;
1195 metrics->length = r->u.object.length;
1196 metrics->canWrapLineAfter = 0;
1197 metrics->isWhitespace = 0;
1198 metrics->isNewline = 0;
1199 metrics->isSoftHyphen = 0;
1200 metrics->isRightToLeft = 0;
1201 metrics->padding = 0;
1202 c->run = r;
1203 c->position = 0; /* there's always one cluster per inline object, so 0 is valid value */
1204 cluster++;
1205
1206 /* it's not fatal if GetMetrics() fails, all returned metrics are ignored */
1207 hr = IDWriteInlineObject_GetMetrics(r->u.object.object, &inlinemetrics);
1208 if (FAILED(hr)) {
1209 memset(&inlinemetrics, 0, sizeof(inlinemetrics));
1210 hr = S_OK;
1211 }
1212 metrics->width = inlinemetrics.width;
1213 r->baseline = inlinemetrics.baseline;
1214 r->height = inlinemetrics.height;
1215
1216 /* FIXME: use resolved breakpoints in this case too */
1217
1218 continue;
1219 }
1220
1221 if (FAILED(hr = layout_shape_run(layout, run)))
1222 WARN("%s: shaping failed, hr %#lx.\n", debugstr_rundescr(&run->descr), hr);
1223
1224 /* baseline derived from font metrics */
1225 layout_get_font_metrics(layout, run->run.fontFace, run->run.fontEmSize, &fontmetrics);
1226 layout_get_font_height(run->run.fontEmSize, &fontmetrics, &r->baseline, &r->height);
1227
1228 layout_set_cluster_metrics(layout, r, &cluster);
1229 }
1230
1231 if (hr == S_OK) {
1232 layout->cluster_count = cluster;
1233 if (cluster)
1234 layout->clustermetrics[cluster-1].canWrapLineAfter = 1;
1235 }
1236
1237 return hr;
1238}
1239
1241{
1242 HRESULT hr;
1243
1244 if (!(layout->recompute & RECOMPUTE_CLUSTERS))
1245 return S_OK;
1246
1247 /* nominal breakpoints are evaluated only once, because string never changes */
1248 if (!layout->nominal_breakpoints)
1249 {
1250 IDWriteTextAnalyzer2 *analyzer;
1251
1252 if (!(layout->nominal_breakpoints = calloc(layout->len, sizeof(*layout->nominal_breakpoints))))
1253 return E_OUTOFMEMORY;
1254
1255 analyzer = get_text_analyzer();
1256
1257 layout_initialize_text_source(layout, 0, layout->len);
1258 if (FAILED(hr = IDWriteTextAnalyzer2_AnalyzeLineBreakpoints(analyzer,
1261 WARN("Line breakpoints analysis failed, hr %#lx.\n", hr);
1262 }
1263
1264 free(layout->actual_breakpoints);
1265 layout->actual_breakpoints = NULL;
1266
1267 hr = layout_compute_runs(layout);
1268
1269 if (TRACE_ON(dwrite)) {
1270 struct layout_run *cur;
1271
1272 LIST_FOR_EACH_ENTRY(cur, &layout->runs, struct layout_run, entry) {
1273 if (cur->kind == LAYOUT_RUN_INLINE)
1274 TRACE("run inline object %p, len %u\n", cur->u.object.object, cur->u.object.length);
1275 else
1276 TRACE("run [%u,%u], len %u, bidilevel %u\n", cur->u.regular.descr.textPosition, cur->u.regular.descr.textPosition +
1277 cur->u.regular.descr.stringLength-1, cur->u.regular.descr.stringLength, cur->u.regular.run.bidiLevel);
1278 }
1279 }
1280
1281 layout->recompute &= ~RECOMPUTE_CLUSTERS;
1282 return hr;
1283}
1284
1285static inline float get_cluster_range_width(const struct dwrite_textlayout *layout, UINT32 start, UINT32 end)
1286{
1287 float width = 0.0f;
1288 for (; start < end; start++)
1289 width += layout->clustermetrics[start].width;
1290 return width;
1291}
1292
1294{
1296 return ((struct layout_range_iface*)h)->iface;
1297}
1298
1299/* A set of parameters that additionally splits resulting runs. It happens after shaping and all text processing,
1300 no glyph changes are possible. It's understandable for drawing effects, because DrawGlyphRun() reports them as
1301 one of the arguments, but it also happens for decorations, so every effective run has uniform
1302 underline/strikethough/effect tuple. */
1307};
1308
1310{
1312 return ((struct layout_range_bool*)h)->value;
1313}
1314
1316{
1318 return ((struct layout_range_bool*)h)->value;
1319}
1320
1323{
1324 params->strikethrough = layout_get_strikethrough_from_pos(layout, pos);
1325 params->underline = layout_get_underline_from_pos(layout, pos);
1326 params->effect = layout_get_effect_from_pos(layout, pos);
1327}
1328
1331{
1332 return left->strikethrough == right->strikethrough &&
1333 left->underline == right->underline &&
1334 left->effect == right->effect;
1335}
1336
1337static void layout_get_erun_font_metrics(const struct dwrite_textlayout *layout, const struct layout_effective_run *erun,
1339{
1340 memset(metrics, 0, sizeof(*metrics));
1341 if (is_layout_gdi_compatible(layout)) {
1342 HRESULT hr = IDWriteFontFace_GetGdiCompatibleMetrics(
1343 erun->run->u.regular.run.fontFace,
1344 erun->run->u.regular.run.fontEmSize,
1345 layout->ppdip,
1346 &layout->transform,
1347 metrics);
1348 if (FAILED(hr))
1349 WARN("failed to get font metrics, 0x%08lx\n", hr);
1350 }
1351 else
1352 IDWriteFontFace_GetMetrics(erun->run->u.regular.run.fontFace, metrics);
1353}
1354
1355/* Effective run is built from consecutive clusters of a single nominal run, 'first_cluster' is 0 based cluster index,
1356 'cluster_count' indicates how many clusters to add, including first one. */
1357static HRESULT layout_add_effective_run(struct dwrite_textlayout *layout, const struct layout_run *r, UINT32 first_cluster,
1358 UINT32 cluster_count, UINT32 line, FLOAT origin_x, struct layout_final_splitting_params *params)
1359{
1361 UINT32 i, start, length, last_cluster;
1362 struct layout_effective_run *run;
1363
1364 if (r->kind == LAYOUT_RUN_INLINE)
1365 {
1366 struct layout_effective_inline *inlineobject;
1367
1368 if (!(inlineobject = malloc(sizeof(*inlineobject))))
1369 return E_OUTOFMEMORY;
1370
1371 inlineobject->object = r->u.object.object;
1372 inlineobject->width = get_cluster_range_width(layout, first_cluster, first_cluster + cluster_count);
1373 inlineobject->origin.x = is_rtl ? origin_x - inlineobject->width : origin_x;
1374 inlineobject->origin.y = 0.0f; /* set after line is built */
1375 inlineobject->align_dx = 0.0f;
1376 inlineobject->baseline = r->baseline;
1377
1378 /* It's not clear how these two are set, possibly directionality
1379 is derived from surrounding text (replaced text could have
1380 different ranges which differ in reading direction). */
1381 inlineobject->is_sideways = FALSE;
1382 inlineobject->is_rtl = FALSE;
1383 inlineobject->line = line;
1384
1385 /* effect assigned from start position and on is used for inline objects */
1386 inlineobject->effect = layout_get_effect_from_pos(layout, layout->clusters[first_cluster].position +
1387 layout->clusters[first_cluster].run->start_position);
1388
1389 list_add_tail(&layout->inlineobjects, &inlineobject->entry);
1390 return S_OK;
1391 }
1392
1393 if (!(run = malloc(sizeof(*run))))
1394 return E_OUTOFMEMORY;
1395
1396 /* No need to iterate for that, use simple fact that:
1397 <last cluster position> = <first cluster position> + <sum of cluster lengths not including last one> */
1398 last_cluster = first_cluster + cluster_count - 1;
1399 length = layout->clusters[last_cluster].position - layout->clusters[first_cluster].position +
1400 layout->clustermetrics[last_cluster].length;
1401
1402 if (!(run->clustermap = calloc(length, sizeof(*run->clustermap))))
1403 {
1404 free(run);
1405 return E_OUTOFMEMORY;
1406 }
1407
1408 run->run = r;
1409 run->start = start = layout->clusters[first_cluster].position;
1410 run->length = length;
1411 run->width = get_cluster_range_width(layout, first_cluster, first_cluster + cluster_count);
1412 memset(&run->bbox, 0, sizeof(run->bbox));
1413
1414 /* Adjust by run width if direction differs. */
1415 if (is_run_rtl(run) != is_rtl)
1416 run->origin.x = origin_x + (is_rtl ? -run->width : run->width);
1417 else
1418 run->origin.x = origin_x;
1419
1420 run->origin.y = 0.0f; /* set after line is built */
1421 run->align_dx = 0.0f;
1422 run->line = line;
1423
1424 if (r->u.regular.run.glyphCount) {
1425 /* Trim leading and trailing clusters. */
1426 run->glyphcount = r->u.regular.run.glyphCount - r->u.regular.clustermap[start];
1427 if (start + length < r->u.regular.descr.stringLength)
1428 run->glyphcount -= r->u.regular.run.glyphCount - r->u.regular.clustermap[start + length];
1429 }
1430 else
1431 run->glyphcount = 0;
1432
1433 /* cluster map needs to be shifted */
1434 for (i = 0; i < length; i++)
1435 run->clustermap[i] = r->u.regular.clustermap[start + i] - r->u.regular.clustermap[start];
1436
1437 run->effect = params->effect;
1438 run->underlined = params->underline;
1439 list_add_tail(&layout->eruns, &run->entry);
1440
1441 /* Strikethrough style is guaranteed to be consistent within effective run,
1442 its width equals to run width, thickness and offset are derived from
1443 font metrics, rest of the values are from layout or run itself */
1444 if (params->strikethrough)
1445 {
1446 struct layout_strikethrough *s;
1448
1449 if (!(s = malloc(sizeof(*s))))
1450 return E_OUTOFMEMORY;
1451
1453 s->s.width = get_cluster_range_width(layout, first_cluster, first_cluster + cluster_count);
1454 s->s.thickness = SCALE_FONT_METRIC(metrics.strikethroughThickness, r->u.regular.run.fontEmSize, &metrics);
1455 /* Negative offset moves it above baseline as Y coordinate grows downward. */
1456 s->s.offset = -SCALE_FONT_METRIC(metrics.strikethroughPosition, r->u.regular.run.fontEmSize, &metrics);
1457 s->s.readingDirection = layout->format.readingdir;
1458 s->s.flowDirection = layout->format.flow;
1459 s->s.localeName = r->u.regular.descr.localeName;
1460 s->s.measuringMode = layout->measuringmode;
1461 s->run = run;
1462
1463 list_add_tail(&layout->strikethrough, &s->entry);
1464 }
1465
1466 return S_OK;
1467}
1468
1470{
1471 switch (layout->format.spacing.method)
1472 {
1474 layout->lines[line].metrics.height = layout->lines[line].height;
1475 layout->lines[line].metrics.baseline = layout->lines[line].baseline;
1476 break;
1478 layout->lines[line].metrics.height = layout->format.spacing.height;
1479 layout->lines[line].metrics.baseline = layout->format.spacing.baseline;
1480 break;
1482 layout->lines[line].metrics.height = layout->lines[line].height * layout->format.spacing.height;
1483 layout->lines[line].metrics.baseline = layout->lines[line].baseline * layout->format.spacing.baseline;
1484 break;
1485 default:
1486 ERR("Unknown spacing method %u\n", layout->format.spacing.method);
1487 }
1488}
1489
1491{
1492 size_t i = layout->metrics.lineCount;
1493
1494 if (!dwrite_array_reserve((void **)&layout->lines, &layout->lines_size, layout->metrics.lineCount + 1,
1495 sizeof(*layout->lines)))
1496 {
1497 return E_OUTOFMEMORY;
1498 }
1499
1500 layout->lines[i].metrics = *metrics;
1501 layout->lines[i].height = metrics->height;
1502 layout->lines[i].baseline = metrics->baseline;
1503
1504 if (layout->format.spacing.method != DWRITE_LINE_SPACING_METHOD_DEFAULT)
1506
1507 layout->metrics.lineCount++;
1508 return S_OK;
1509}
1510
1511static inline struct layout_effective_run *layout_get_next_erun(const struct dwrite_textlayout *layout,
1512 const struct layout_effective_run *cur)
1513{
1514 struct list *e;
1515
1516 if (!cur)
1517 e = list_head(&layout->eruns);
1518 else
1519 e = list_next(&layout->eruns, &cur->entry);
1520 if (!e)
1521 return NULL;
1522 return LIST_ENTRY(e, struct layout_effective_run, entry);
1523}
1524
1525static inline struct layout_effective_run *layout_get_prev_erun(const struct dwrite_textlayout *layout,
1526 const struct layout_effective_run *cur)
1527{
1528 struct list *e;
1529
1530 if (!cur)
1531 e = list_tail(&layout->eruns);
1532 else
1533 e = list_prev(&layout->eruns, &cur->entry);
1534 if (!e)
1535 return NULL;
1536 return LIST_ENTRY(e, struct layout_effective_run, entry);
1537}
1538
1540 const struct layout_effective_inline *cur)
1541{
1542 struct list *e;
1543
1544 if (!cur)
1545 e = list_head(&layout->inlineobjects);
1546 else
1547 e = list_next(&layout->inlineobjects, &cur->entry);
1548 if (!e)
1549 return NULL;
1550 return LIST_ENTRY(e, struct layout_effective_inline, entry);
1551}
1552
1553static float layout_get_line_width(const struct dwrite_textlayout *layout, const struct layout_effective_run *erun,
1554 const struct layout_effective_inline *inrun, UINT32 line)
1555{
1556 FLOAT width = 0.0f;
1557
1558 while (erun && erun->line == line) {
1559 width += erun->width;
1560 erun = layout_get_next_erun(layout, erun);
1561 if (!erun)
1562 break;
1563 }
1564
1565 while (inrun && inrun->line == line) {
1566 width += inrun->width;
1567 inrun = layout_get_next_inline_run(layout, inrun);
1568 if (!inrun)
1569 break;
1570 }
1571
1572 return width;
1573}
1574
1576{
1577 *det = m->m11 * m->m22 - m->m12 * m->m21;
1578 /* on certain conditions we can skip transform */
1579 return (!memcmp(m, &identity, sizeof(*m)) || fabsf(*det) <= 1e-10f);
1580}
1581
1582static inline void layout_apply_snapping(D2D1_POINT_2F *vec, BOOL skiptransform, FLOAT ppdip,
1583 const DWRITE_MATRIX *m, FLOAT det)
1584{
1585 if (!skiptransform) {
1587
1588 /* apply transform */
1589 vec->x *= ppdip;
1590 vec->y *= ppdip;
1591
1592 vec2.x = m->m11 * vec->x + m->m21 * vec->y + m->dx;
1593 vec2.y = m->m12 * vec->x + m->m22 * vec->y + m->dy;
1594
1595 /* snap */
1596 vec2.x = floorf(vec2.x + 0.5f);
1597 vec2.y = floorf(vec2.y + 0.5f);
1598
1599 /* apply inverted transform, we don't care about X component at this point */
1600 vec->x = (m->m22 * vec2.x - m->m21 * vec2.y + m->m21 * m->dy - m->m22 * m->dx) / det;
1601 vec->x /= ppdip;
1602
1603 vec->y = (-m->m12 * vec2.x + m->m11 * vec2.y - (m->m11 * m->dy - m->m12 * m->dx)) / det;
1604 vec->y /= ppdip;
1605 }
1606 else {
1607 vec->x = floorf(vec->x * ppdip + 0.5f) / ppdip;
1608 vec->y = floorf(vec->y * ppdip + 0.5f) / ppdip;
1609 }
1610}
1611
1613{
1615 struct layout_effective_inline *inrun;
1616 struct layout_effective_run *erun;
1617
1618 erun = layout_get_next_erun(layout, NULL);
1619 inrun = layout_get_next_inline_run(layout, NULL);
1620
1621 while (erun) {
1622 erun->align_dx = 0.0f;
1623 erun = layout_get_next_erun(layout, erun);
1624 }
1625
1626 while (inrun) {
1627 inrun->align_dx = 0.0f;
1628 inrun = layout_get_next_inline_run(layout, inrun);
1629 }
1630
1631 layout->metrics.left = is_rtl ? layout->metrics.layoutWidth - layout->metrics.width : 0.0f;
1632}
1633
1635{
1637 struct layout_effective_inline *inrun;
1638 struct layout_effective_run *erun;
1639 UINT32 line;
1640
1641 erun = layout_get_next_erun(layout, NULL);
1642 inrun = layout_get_next_inline_run(layout, NULL);
1643
1644 for (line = 0; line < layout->metrics.lineCount; line++) {
1645 FLOAT width = layout_get_line_width(layout, erun, inrun, line);
1646 FLOAT shift = layout->metrics.layoutWidth - width;
1647
1648 if (is_rtl)
1649 shift *= -1.0f;
1650
1651 while (erun && erun->line == line) {
1652 erun->align_dx = shift;
1653 erun = layout_get_next_erun(layout, erun);
1654 }
1655
1656 while (inrun && inrun->line == line) {
1657 inrun->align_dx = shift;
1658 inrun = layout_get_next_inline_run(layout, inrun);
1659 }
1660 }
1661
1662 layout->metrics.left = is_rtl ? 0.0f : layout->metrics.layoutWidth - layout->metrics.width;
1663}
1664
1665static inline float layout_get_centered_shift(const struct dwrite_textlayout *layout, BOOL skiptransform,
1666 FLOAT width, FLOAT det)
1667{
1668 if (is_layout_gdi_compatible(layout)) {
1669 D2D1_POINT_2F vec = { layout->metrics.layoutWidth - width, 0.0f};
1670 layout_apply_snapping(&vec, skiptransform, layout->ppdip, &layout->transform, det);
1671 return floorf(vec.x / 2.0f);
1672 }
1673 else
1674 return (layout->metrics.layoutWidth - width) / 2.0f;
1675}
1676
1678{
1680 struct layout_effective_inline *inrun;
1681 struct layout_effective_run *erun;
1682 BOOL skiptransform;
1683 UINT32 line;
1684 FLOAT det;
1685
1686 erun = layout_get_next_erun(layout, NULL);
1687 inrun = layout_get_next_inline_run(layout, NULL);
1688
1689 skiptransform = should_skip_transform(&layout->transform, &det);
1690
1691 for (line = 0; line < layout->metrics.lineCount; line++) {
1692 FLOAT width = layout_get_line_width(layout, erun, inrun, line);
1693 FLOAT shift = layout_get_centered_shift(layout, skiptransform, width, det);
1694
1695 if (is_rtl)
1696 shift *= -1.0f;
1697
1698 while (erun && erun->line == line) {
1699 erun->align_dx = shift;
1700 erun = layout_get_next_erun(layout, erun);
1701 }
1702
1703 while (inrun && inrun->line == line) {
1704 inrun->align_dx = shift;
1705 inrun = layout_get_next_inline_run(layout, inrun);
1706 }
1707 }
1708
1709 layout->metrics.left = (layout->metrics.layoutWidth - layout->metrics.width) / 2.0f;
1710}
1711
1713{
1714 switch (layout->format.textalignment)
1715 {
1718 break;
1721 break;
1724 break;
1726 FIXME("alignment %d not implemented\n", layout->format.textalignment);
1727 break;
1728 default:
1729 ;
1730 }
1731}
1732
1734{
1735 struct layout_effective_inline *inrun;
1736 struct layout_effective_run *erun;
1737 FLOAT origin_y = 0.0f;
1738 UINT32 line;
1739
1740 /* alignment mode defines origin, after that all run origins are updated
1741 the same way */
1742
1743 switch (layout->format.paralign)
1744 {
1746 origin_y = 0.0f;
1747 break;
1749 origin_y = layout->metrics.layoutHeight - layout->metrics.height;
1750 break;
1752 origin_y = (layout->metrics.layoutHeight - layout->metrics.height) / 2.0f;
1753 break;
1754 default:
1755 ;
1756 }
1757
1758 layout->metrics.top = origin_y;
1759
1760 erun = layout_get_next_erun(layout, NULL);
1761 inrun = layout_get_next_inline_run(layout, NULL);
1762 for (line = 0; line < layout->metrics.lineCount; line++)
1763 {
1764 float pos_y = origin_y + layout->lines[line].metrics.baseline;
1765
1766 while (erun && erun->line == line) {
1767 erun->origin.y = pos_y;
1768 erun = layout_get_next_erun(layout, erun);
1769 }
1770
1771 while (inrun && inrun->line == line) {
1772 inrun->origin.y = pos_y - inrun->baseline;
1773 inrun = layout_get_next_inline_run(layout, inrun);
1774 }
1775
1776 origin_y += layout->lines[line].metrics.height;
1777 }
1778}
1779
1781 const WCHAR *locale; /* points to range data, no additional allocation */
1782 IUnknown *effect; /* does not hold another reference */
1783};
1784
1787{
1788 params->locale = erun->run->u.regular.descr.localeName;
1789 params->effect = erun->effect;
1790}
1791
1794{
1795 return left->effect == right->effect && !wcsicmp(left->locale, right->locale);
1796}
1797
1799 struct layout_effective_run *last)
1800{
1801 FLOAT thickness, offset, runheight;
1802 struct layout_effective_run *cur;
1804
1805 if (first == layout_get_prev_erun(layout, last)) {
1807 thickness = SCALE_FONT_METRIC(metrics.underlineThickness, first->run->u.regular.run.fontEmSize, &metrics);
1808 offset = SCALE_FONT_METRIC(metrics.underlinePosition, first->run->u.regular.run.fontEmSize, &metrics);
1809 runheight = SCALE_FONT_METRIC(metrics.capHeight, first->run->u.regular.run.fontEmSize, &metrics);
1810 }
1811 else {
1812 FLOAT width = 0.0f;
1813
1814 /* Single underline is added for consecutive underlined runs. In this case underline parameters are
1815 calculated as weighted average, where run width acts as a weight. */
1816 thickness = offset = runheight = 0.0f;
1817 cur = first;
1818 do {
1820
1821 thickness += SCALE_FONT_METRIC(metrics.underlineThickness, cur->run->u.regular.run.fontEmSize, &metrics) * cur->width;
1822 offset += SCALE_FONT_METRIC(metrics.underlinePosition, cur->run->u.regular.run.fontEmSize, &metrics) * cur->width;
1823 runheight = max(SCALE_FONT_METRIC(metrics.capHeight, cur->run->u.regular.run.fontEmSize, &metrics), runheight);
1824 width += cur->width;
1825
1826 cur = layout_get_next_erun(layout, cur);
1827 } while (cur != last);
1828
1829 thickness /= width;
1830 offset /= width;
1831 }
1832
1833 cur = first;
1834 do {
1835 struct layout_underline_splitting_params params, prev_params;
1836 struct layout_effective_run *next, *w;
1837 struct layout_underline *u;
1838
1840 while ((next = layout_get_next_erun(layout, cur)) != last) {
1842 if (!is_same_u_splitting(&prev_params, &params))
1843 break;
1844 cur = next;
1845 }
1846
1847 if (!(u = malloc(sizeof(*u))))
1848 return E_OUTOFMEMORY;
1849
1850 w = cur;
1851 u->u.width = 0.0f;
1852 while (w != next) {
1853 u->u.width += w->width;
1854 w = layout_get_next_erun(layout, w);
1855 }
1856
1857 u->u.thickness = thickness;
1858 /* Font metrics convention is to have it negative when below baseline, for rendering
1859 however Y grows from baseline down for horizontal baseline. */
1860 u->u.offset = -offset;
1861 u->u.runHeight = runheight;
1862 u->u.readingDirection = is_run_rtl(cur) ? DWRITE_READING_DIRECTION_RIGHT_TO_LEFT :
1864 u->u.flowDirection = layout->format.flow;
1865 u->u.localeName = cur->run->u.regular.descr.localeName;
1866 u->u.measuringMode = layout->measuringmode;
1867 u->run = cur;
1868 list_add_tail(&layout->underlines, &u->entry);
1869
1870 cur = next;
1871 } while (cur != last);
1872
1873 return S_OK;
1874}
1875
1876static inline struct regular_layout_run * layout_get_last_run(const struct dwrite_textlayout *layout)
1877{
1878 struct layout_run *r;
1879 struct list *e;
1880
1881 if (!(e = list_tail(&layout->runs))) return NULL;
1882 r = LIST_ENTRY(e, struct layout_run, entry);
1883 if (r->kind != LAYOUT_RUN_REGULAR) return NULL;
1884 return &r->u.regular;
1885}
1886
1887/* Adds a dummy line if:
1888 - there's no text, metrics come from first range in this case;
1889 - last ended with a mandatory break, metrics come from last text position.
1890*/
1892{
1894 DWRITE_FONT_METRICS fontmetrics;
1895 struct regular_layout_run *run;
1896 IDWriteFontFace *fontface;
1897 float size;
1898 HRESULT hr;
1899
1900 if (layout->cluster_count && !layout->clustermetrics[layout->cluster_count - 1].isNewline)
1901 return S_OK;
1902
1903 if (!layout->cluster_count)
1904 {
1905 if (FAILED(hr = layout_run_get_last_resort_font(layout, get_layout_range_by_pos(layout, 0), &fontface, &size)))
1906 return hr;
1907 }
1908 else if (!(run = layout_get_last_run(layout)))
1909 {
1910 return S_OK;
1911 }
1912 else
1913 {
1914 fontface = run->run.fontFace;
1915 IDWriteFontFace_AddRef(fontface);
1916 size = run->run.fontEmSize;
1917 }
1918
1919 layout_get_font_metrics(layout, fontface, size, &fontmetrics);
1920 layout_get_font_height(size, &fontmetrics, &metrics.baseline, &metrics.height);
1921 IDWriteFontFace_Release(fontface);
1922
1923 return layout_set_line_metrics(layout, &metrics);
1924}
1925
1926static void layout_add_line(struct dwrite_textlayout *layout, UINT32 first_cluster, UINT32 last_cluster,
1927 UINT32 *textpos)
1928{
1930 struct layout_final_splitting_params params, prev_params;
1931 DWRITE_INLINE_OBJECT_METRICS sign_metrics = { 0 };
1932 UINT32 line = layout->metrics.lineCount, i;
1934 UINT32 index, start, pos = *textpos;
1935 FLOAT descent, trailingspacewidth;
1936 BOOL append_trimming_run = FALSE;
1937 const struct layout_run *run;
1938 float width = 0.0f, origin_x;
1939 HRESULT hr;
1940
1941 /* Take a look at clusters we got for this line in reverse order to set trailing properties for current line */
1942 for (index = last_cluster, trailingspacewidth = 0.0f; index >= first_cluster; index--) {
1943 DWRITE_CLUSTER_METRICS *cluster = &layout->clustermetrics[index];
1944 struct layout_cluster *lc = &layout->clusters[index];
1945 WCHAR ch;
1946
1947 /* This also filters out clusters added from inline objects, those are never
1948 treated as a white space. */
1949 if (!cluster->isWhitespace)
1950 break;
1951
1952 /* Every isNewline cluster is also isWhitespace, but not every
1953 newline character cluster has isNewline set, so go back to original string. */
1954 ch = lc->run->u.regular.descr.string[lc->position];
1955 if (cluster->length == 1 && lb_is_newline_char(ch))
1956 metrics.newlineLength += cluster->length;
1957
1958 metrics.trailingWhitespaceLength += cluster->length;
1959 trailingspacewidth += cluster->width;
1960
1961 if (index == 0)
1962 break;
1963 }
1964
1965 /* Line metrics length includes trailing whitespace length too */
1966 for (i = first_cluster; i <= last_cluster; i++)
1967 metrics.length += layout->clustermetrics[i].length;
1968
1969 /* Ignore trailing whitespaces */
1970 while (last_cluster > first_cluster) {
1971 if (!layout->clustermetrics[last_cluster].isWhitespace)
1972 break;
1973
1974 last_cluster--;
1975 }
1976
1977 /* Does not include trailing space width */
1978 if (!layout->clustermetrics[last_cluster].isWhitespace)
1979 width = get_cluster_range_width(layout, first_cluster, last_cluster + 1);
1980
1981 /* Append trimming run if necessary */
1982 if (width > layout->metrics.layoutWidth && layout->format.trimmingsign != NULL &&
1983 layout->format.trimming.granularity != DWRITE_TRIMMING_GRANULARITY_NONE) {
1984 FLOAT trimmed_width = width;
1985
1986 hr = IDWriteInlineObject_GetMetrics(layout->format.trimmingsign, &sign_metrics);
1987 if (SUCCEEDED(hr)) {
1988 while (last_cluster > first_cluster) {
1989 if (trimmed_width + sign_metrics.width <= layout->metrics.layoutWidth)
1990 break;
1991 if (layout->format.trimming.granularity == DWRITE_TRIMMING_GRANULARITY_CHARACTER)
1992 trimmed_width -= layout->clustermetrics[last_cluster--].width;
1993 else {
1994 while (last_cluster > first_cluster) {
1995 trimmed_width -= layout->clustermetrics[last_cluster].width;
1996 if (layout->clustermetrics[last_cluster--].canWrapLineAfter)
1997 break;
1998 }
1999 }
2000 }
2001 append_trimming_run = TRUE;
2002 }
2003 else
2004 WARN("Failed to get trimming sign metrics, lines won't be trimmed, hr %#lx.\n", hr);
2005
2006 width = trimmed_width + sign_metrics.width;
2007 }
2008
2010 prev_params = params;
2011 run = layout->clusters[first_cluster].run;
2012
2013 /* Form runs from a range of clusters; this is what will be reported with DrawGlyphRun() */
2014 origin_x = is_rtl ? layout->metrics.layoutWidth : 0.0f;
2015 for (start = first_cluster, i = first_cluster; i <= last_cluster; i++) {
2017
2018 if (run != layout->clusters[i].run || !is_same_splitting_params(&prev_params, &params)) {
2019 hr = layout_add_effective_run(layout, run, start, i - start, line, origin_x, &prev_params);
2020 if (FAILED(hr))
2021 return;
2022
2023 origin_x += is_rtl ? -get_cluster_range_width(layout, start, i) :
2025 run = layout->clusters[i].run;
2026 start = i;
2027 }
2028
2029 prev_params = params;
2030 pos += layout->clustermetrics[i].length;
2031 }
2032
2033 /* Final run from what's left from cluster range */
2034 hr = layout_add_effective_run(layout, run, start, i - start, line, origin_x, &prev_params);
2035 if (FAILED(hr))
2036 return;
2037
2038 if (get_cluster_range_width(layout, start, i) + sign_metrics.width > layout->metrics.layoutWidth)
2039 append_trimming_run = FALSE;
2040
2041 if (append_trimming_run) {
2042 struct layout_effective_inline *trimming_sign;
2043
2044 if (!(trimming_sign = calloc(1, sizeof(*trimming_sign))))
2045 return;
2046
2047 trimming_sign->object = layout->format.trimmingsign;
2048 trimming_sign->width = sign_metrics.width;
2049 origin_x += is_rtl ? -get_cluster_range_width(layout, start, i) : get_cluster_range_width(layout, start, i);
2050 trimming_sign->origin.x = is_rtl ? origin_x - trimming_sign->width : origin_x;
2051 trimming_sign->origin.y = 0.0f; /* set after line is built */
2052 trimming_sign->align_dx = 0.0f;
2053 trimming_sign->baseline = sign_metrics.baseline;
2054
2055 trimming_sign->is_sideways = FALSE;
2056 trimming_sign->is_rtl = FALSE;
2057 trimming_sign->line = line;
2058
2059 trimming_sign->effect = layout_get_effect_from_pos(layout, layout->clusters[i].position +
2060 layout->clusters[i].run->start_position);
2061
2062 list_add_tail(&layout->inlineobjects, &trimming_sign->entry);
2063 }
2064
2065 /* Look for max baseline and descent for this line */
2066 for (index = first_cluster, metrics.baseline = 0.0f, descent = 0.0f; index <= last_cluster; index++) {
2067 const struct layout_run *cur = layout->clusters[index].run;
2068 FLOAT cur_descent = cur->height - cur->baseline;
2069
2070 if (cur->baseline > metrics.baseline)
2071 metrics.baseline = cur->baseline;
2072 if (cur_descent > descent)
2073 descent = cur_descent;
2074 }
2075
2076 layout->metrics.width = max(width, layout->metrics.width);
2077 layout->metrics.widthIncludingTrailingWhitespace = max(width + trailingspacewidth,
2079
2080 metrics.height = descent + metrics.baseline;
2081 metrics.isTrimmed = append_trimming_run || width > layout->metrics.layoutWidth;
2083
2084 *textpos += metrics.length;
2085}
2086
2088{
2089 struct layout_effective_inline *inrun;
2090 struct layout_effective_run *erun;
2091 FLOAT origin_y;
2092 UINT32 line;
2093
2094 /* Now all line info is here, update effective runs positions in flow direction */
2095 erun = layout_get_next_erun(layout, NULL);
2096 inrun = layout_get_next_inline_run(layout, NULL);
2097
2098 for (line = 0, origin_y = 0.0f; line < layout->metrics.lineCount; line++)
2099 {
2100 float pos_y = origin_y + layout->lines[line].metrics.baseline;
2101
2102 /* For all runs on this line */
2103 while (erun && erun->line == line) {
2104 erun->origin.y = pos_y;
2105 erun = layout_get_next_erun(layout, erun);
2106 }
2107
2108 /* Same for inline runs */
2109 while (inrun && inrun->line == line) {
2110 inrun->origin.y = pos_y - inrun->baseline;
2111 inrun = layout_get_next_inline_run(layout, inrun);
2112 }
2113
2114 origin_y += layout->lines[line].metrics.height;
2115 }
2116
2117 layout->metrics.height = origin_y;
2118
2119 /* Initial paragraph alignment is always near */
2120 if (layout->format.paralign != DWRITE_PARAGRAPH_ALIGNMENT_NEAR)
2122}
2123
2124static BOOL layout_can_wrap_after(const struct dwrite_textlayout *layout, UINT32 cluster)
2125{
2126 if (layout->format.wrapping == DWRITE_WORD_WRAPPING_CHARACTER)
2127 return TRUE;
2128
2129 return layout->clustermetrics[cluster].canWrapLineAfter;
2130}
2131
2133{
2135 struct layout_effective_run *erun, *first_underlined;
2136 UINT32 i, start, textpos, last_breaking_point;
2138 FLOAT width;
2139 UINT32 line;
2140 HRESULT hr;
2141
2142 if (!(layout->recompute & RECOMPUTE_LINES))
2143 return S_OK;
2144
2145 free_layout_eruns(layout);
2146
2147 hr = layout_compute(layout);
2148 if (FAILED(hr))
2149 return hr;
2150
2151 layout->metrics.lineCount = 0;
2152 memset(&metrics, 0, sizeof(metrics));
2153
2154 layout->metrics.height = 0.0f;
2155 layout->metrics.width = 0.0f;
2157
2158 last_breaking_point = ~0u;
2159
2160 for (i = 0, start = 0, width = 0.0f, textpos = 0; i < layout->cluster_count; i++) {
2161 BOOL overflow = FALSE;
2162
2163 while (i < layout->cluster_count && !layout->clustermetrics[i].isNewline) {
2164 /* Check for overflow */
2165 overflow = ((width + layout->clustermetrics[i].width > layout->metrics.layoutWidth) &&
2166 (layout->format.wrapping != DWRITE_WORD_WRAPPING_NO_WRAP));
2167 if (overflow)
2168 break;
2169
2170 if (layout_can_wrap_after(layout, i))
2171 last_breaking_point = i;
2172 width += layout->clustermetrics[i].width;
2173 i++;
2174 }
2175 i = min(i, layout->cluster_count - 1);
2176
2177 /* Ignore if overflown on whitespace */
2178 if (overflow && !(layout->clustermetrics[i].isWhitespace && layout_can_wrap_after(layout, i))) {
2179 /* Use most recently found breaking point */
2180 if (last_breaking_point != ~0u) {
2181 i = last_breaking_point;
2182 last_breaking_point = ~0u;
2183 }
2184 else {
2185 /* Otherwise proceed forward to next newline or breaking point */
2186 for (; i < layout->cluster_count; i++)
2187 if (layout_can_wrap_after(layout, i) || layout->clustermetrics[i].isNewline)
2188 break;
2189 }
2190 }
2191 i = min(i, layout->cluster_count - 1);
2192
2193 layout_add_line(layout, start, i, &textpos);
2194 start = i + 1;
2195 width = 0.0f;
2196 }
2197
2199 return hr;
2200
2201 layout->metrics.left = is_rtl ? layout->metrics.layoutWidth - layout->metrics.width : 0.0f;
2202 layout->metrics.top = 0.0f;
2203 layout->metrics.maxBidiReorderingDepth = 1; /* FIXME */
2204
2205 /* Add explicit underlined runs */
2206 erun = layout_get_next_erun(layout, NULL);
2207 first_underlined = erun && erun->underlined ? erun : NULL;
2208 for (line = 0; line < layout->metrics.lineCount; line++) {
2209 while (erun && erun->line == line) {
2210 erun = layout_get_next_erun(layout, erun);
2211
2212 if (first_underlined && (!erun || !erun->underlined)) {
2213 layout_add_underline(layout, first_underlined, erun);
2214 first_underlined = NULL;
2215 }
2216 else if (!first_underlined && erun && erun->underlined)
2217 first_underlined = erun;
2218 }
2219 }
2220
2221 /* Position runs in flow direction */
2223
2224 /* Initial alignment is always leading */
2225 if (layout->format.textalignment != DWRITE_TEXT_ALIGNMENT_LEADING)
2227
2228 layout->recompute &= ~RECOMPUTE_LINES;
2229 return hr;
2230}
2231
2234{
2235 struct layout_range_spacing const *range_spacing = (struct layout_range_spacing*)h;
2236 struct layout_range_iface const *range_iface = (struct layout_range_iface*)h;
2237 struct layout_range_bool const *range_bool = (struct layout_range_bool*)h;
2238 struct layout_range const *range = (struct layout_range*)h;
2239
2240 switch (attr) {
2242 return range->weight == value->u.weight;
2244 return range->style == value->u.style;
2246 return range->stretch == value->u.stretch;
2248 return range->fontsize == value->u.fontsize;
2250 return range->object == value->u.object;
2252 return range_iface->iface == value->u.effect;
2254 return range_bool->value == value->u.underline;
2256 return range_bool->value == value->u.strikethrough;
2258 return range->pair_kerning == value->u.pair_kerning;
2260 return range->collection == value->u.collection;
2262 return !wcsicmp(range->locale, value->u.locale);
2264 return !wcscmp(range->fontfamily, value->u.fontfamily);
2266 return range_spacing->leading == value->u.spacing.leading &&
2267 range_spacing->trailing == value->u.spacing.trailing &&
2268 range_spacing->min_advance == value->u.spacing.min_advance;
2270 return range_iface->iface == (IUnknown*)value->u.typography;
2271 default:
2272 ;
2273 }
2274
2275 return FALSE;
2276}
2277
2278static inline BOOL is_same_layout_attributes(struct layout_range_header const *hleft, struct layout_range_header const *hright)
2279{
2280 switch (hleft->kind)
2281 {
2283 {
2284 struct layout_range const *left = (struct layout_range const*)hleft;
2285 struct layout_range const *right = (struct layout_range const*)hright;
2286 return left->weight == right->weight &&
2287 left->style == right->style &&
2288 left->stretch == right->stretch &&
2289 left->fontsize == right->fontsize &&
2290 left->object == right->object &&
2291 left->pair_kerning == right->pair_kerning &&
2292 left->collection == right->collection &&
2293 !wcsicmp(left->locale, right->locale) &&
2294 !wcscmp(left->fontfamily, right->fontfamily);
2295 }
2298 {
2299 struct layout_range_bool const *left = (struct layout_range_bool const*)hleft;
2300 struct layout_range_bool const *right = (struct layout_range_bool const*)hright;
2301 return left->value == right->value;
2302 }
2305 {
2306 struct layout_range_iface const *left = (struct layout_range_iface const*)hleft;
2307 struct layout_range_iface const *right = (struct layout_range_iface const*)hright;
2308 return left->iface == right->iface;
2309 }
2311 {
2312 struct layout_range_spacing const *left = (struct layout_range_spacing const*)hleft;
2313 struct layout_range_spacing const *right = (struct layout_range_spacing const*)hright;
2314 return left->leading == right->leading &&
2315 left->trailing == right->trailing &&
2316 left->min_advance == right->min_advance;
2317 }
2318 default:
2319 FIXME("unknown range kind %d\n", hleft->kind);
2320 return FALSE;
2321 }
2322}
2323
2325{
2326 return left->startPosition == right->startPosition && left->length == right->length;
2327}
2328
2329/* Allocates range and inits it with default values from text format. */
2332{
2333 struct layout_range_header *h;
2334
2335 switch (kind)
2336 {
2338 {
2339 struct layout_range *range;
2340
2341 if (!(range = calloc(1, sizeof(*range))))
2342 return NULL;
2343
2344 range->weight = layout->format.weight;
2345 range->style = layout->format.style;
2346 range->stretch = layout->format.stretch;
2347 range->fontsize = layout->format.fontsize;
2348
2349 range->fontfamily = wcsdup(layout->format.family_name);
2350 if (!range->fontfamily)
2351 {
2352 free(range);
2353 return NULL;
2354 }
2355
2356 range->collection = layout->format.collection;
2357 if (range->collection)
2358 IDWriteFontCollection_AddRef(range->collection);
2359 wcscpy(range->locale, layout->format.locale);
2360
2361 h = &range->h;
2362 break;
2363 }
2366 {
2367 struct layout_range_bool *range;
2368
2369 if (!(range = calloc(1, sizeof(*range))))
2370 return NULL;
2371
2372 h = &range->h;
2373 break;
2374 }
2377 {
2378 struct layout_range_iface *range;
2379
2380 if (!(range = calloc(1, sizeof(*range))))
2381 return NULL;
2382
2383 h = &range->h;
2384 break;
2385 }
2387 {
2389
2390 if (!(range = calloc(1, sizeof(*range))))
2391 return NULL;
2392
2393 h = &range->h;
2394 break;
2395 }
2396 default:
2397 FIXME("unknown range kind %d\n", kind);
2398 return NULL;
2399 }
2400
2401 h->kind = kind;
2402 h->range = *r;
2403 return h;
2404}
2405
2407{
2408 struct layout_range_header *ret;
2409
2410 switch (h->kind)
2411 {
2413 {
2414 struct layout_range *from = (struct layout_range *)h, *range;
2415
2416 if (!(range = malloc(sizeof(*range))))
2417 return NULL;
2418
2419 *range = *from;
2420 range->fontfamily = wcsdup(from->fontfamily);
2421 if (!range->fontfamily)
2422 {
2423 free(range);
2424 return NULL;
2425 }
2426
2427 /* update refcounts */
2428 if (range->object)
2429 IDWriteInlineObject_AddRef(range->object);
2430 if (range->collection)
2431 IDWriteFontCollection_AddRef(range->collection);
2432 ret = &range->h;
2433 break;
2434 }
2437 {
2438 struct layout_range_bool *strike = malloc(sizeof(*strike));
2439 if (!strike) return NULL;
2440
2441 *strike = *(struct layout_range_bool*)h;
2442 ret = &strike->h;
2443 break;
2444 }
2447 {
2448 struct layout_range_iface *effect = malloc(sizeof(*effect));
2449 if (!effect) return NULL;
2450
2451 *effect = *(struct layout_range_iface*)h;
2452 if (effect->iface)
2453 IUnknown_AddRef(effect->iface);
2454 ret = &effect->h;
2455 break;
2456 }
2458 {
2459 struct layout_range_spacing *spacing = malloc(sizeof(*spacing));
2460 if (!spacing) return NULL;
2461
2462 *spacing = *(struct layout_range_spacing*)h;
2463 ret = &spacing->h;
2464 break;
2465 }
2466 default:
2467 FIXME("unknown range kind %d\n", h->kind);
2468 return NULL;
2469 }
2470
2471 ret->range = *r;
2472 return ret;
2473}
2474
2476{
2477 if (!h)
2478 return;
2479
2480 switch (h->kind)
2481 {
2483 {
2484 struct layout_range *range = (struct layout_range*)h;
2485
2486 if (range->object)
2487 IDWriteInlineObject_Release(range->object);
2488 if (range->collection)
2489 IDWriteFontCollection_Release(range->collection);
2490 free(range->fontfamily);
2491 break;
2492 }
2495 {
2496 struct layout_range_iface *range = (struct layout_range_iface*)h;
2497 if (range->iface)
2498 IUnknown_Release(range->iface);
2499 break;
2500 }
2501 default:
2502 ;
2503 }
2504
2505 free(h);
2506}
2507
2509{
2510 struct layout_range_header *cur, *cur2;
2511
2512 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &layout->ranges, struct layout_range_header, entry) {
2513 list_remove(&cur->entry);
2515 }
2516
2518 list_remove(&cur->entry);
2520 }
2521
2523 list_remove(&cur->entry);
2525 }
2526
2528 list_remove(&cur->entry);
2530 }
2531
2533 list_remove(&cur->entry);
2535 }
2536
2538 list_remove(&cur->entry);
2540 }
2541}
2542
2544{
2545 struct layout_range_header *cur;
2546
2548
2549 if (cur->range.startPosition > range->startPosition)
2550 return NULL;
2551
2552 if ((cur->range.startPosition + cur->range.length < range->startPosition + range->length) &&
2553 (range->startPosition < cur->range.startPosition + cur->range.length))
2554 return NULL;
2555 if (cur->range.startPosition + cur->range.length >= range->startPosition + range->length)
2556 return cur;
2557 }
2558
2559 return NULL;
2560}
2561
2563{
2564 if (*dest == value) return FALSE;
2565
2566 if (*dest)
2567 IUnknown_Release(*dest);
2568 *dest = value;
2569 if (*dest)
2570 IUnknown_AddRef(*dest);
2571
2572 return TRUE;
2573}
2574
2576{
2577 struct layout_range_spacing *dest_spacing = (struct layout_range_spacing*)h;
2578 struct layout_range_iface *dest_iface = (struct layout_range_iface*)h;
2579 struct layout_range_bool *dest_bool = (struct layout_range_bool*)h;
2580 struct layout_range *dest = (struct layout_range*)h;
2581
2582 BOOL changed = FALSE;
2583
2584 switch (attr) {
2586 changed = dest->weight != value->u.weight;
2587 dest->weight = value->u.weight;
2588 break;
2590 changed = dest->style != value->u.style;
2591 dest->style = value->u.style;
2592 break;
2594 changed = dest->stretch != value->u.stretch;
2595 dest->stretch = value->u.stretch;
2596 break;
2598 changed = dest->fontsize != value->u.fontsize;
2599 dest->fontsize = value->u.fontsize;
2600 break;
2602 changed = set_layout_range_iface_attr((IUnknown**)&dest->object, (IUnknown*)value->u.object);
2603 break;
2605 changed = set_layout_range_iface_attr(&dest_iface->iface, value->u.effect);
2606 break;
2608 changed = dest_bool->value != value->u.underline;
2609 dest_bool->value = value->u.underline;
2610 break;
2612 changed = dest_bool->value != value->u.strikethrough;
2613 dest_bool->value = value->u.strikethrough;
2614 break;
2616 changed = dest->pair_kerning != value->u.pair_kerning;
2617 dest->pair_kerning = value->u.pair_kerning;
2618 break;
2620 changed = set_layout_range_iface_attr((IUnknown**)&dest->collection, (IUnknown*)value->u.collection);
2621 break;
2623 changed = !!wcsicmp(dest->locale, value->u.locale);
2624 if (changed)
2625 {
2626 wcscpy(dest->locale, value->u.locale);
2627 wcslwr(dest->locale);
2628 }
2629 break;
2631 changed = !!wcscmp(dest->fontfamily, value->u.fontfamily);
2632 if (changed)
2633 {
2634 free(dest->fontfamily);
2635 dest->fontfamily = wcsdup(value->u.fontfamily);
2636 }
2637 break;
2639 changed = dest_spacing->leading != value->u.spacing.leading ||
2640 dest_spacing->trailing != value->u.spacing.trailing ||
2641 dest_spacing->min_advance != value->u.spacing.min_advance;
2642 dest_spacing->leading = value->u.spacing.leading;
2643 dest_spacing->trailing = value->u.spacing.trailing;
2644 dest_spacing->min_advance = value->u.spacing.min_advance;
2645 break;
2647 changed = set_layout_range_iface_attr(&dest_iface->iface, (IUnknown*)value->u.typography);
2648 break;
2649 default:
2650 ;
2651 }
2652
2653 return changed;
2654}
2655
2657{
2658 return (inner->startPosition >= outer->startPosition) &&
2659 (inner->startPosition + inner->length <= outer->startPosition + outer->length);
2660}
2661
2663{
2664 if (r) *r = h->range;
2665 return S_OK;
2666}
2667
2668/* Sets attribute value for given range, does all needed splitting/merging of existing ranges. */
2670{
2671 struct layout_range_header *cur, *right, *left, *outer;
2672 BOOL changed = FALSE;
2673 struct list *ranges;
2675
2676 /* ignore zero length ranges */
2677 if (value->range.length == 0)
2678 return S_OK;
2679
2680 if (~0u - value->range.startPosition < value->range.length)
2681 return E_INVALIDARG;
2682
2683 /* select from ranges lists */
2684 switch (attr)
2685 {
2695 ranges = &layout->ranges;
2696 break;
2698 ranges = &layout->underline_ranges;
2699 break;
2701 ranges = &layout->strike_ranges;
2702 break;
2704 ranges = &layout->effects;
2705 break;
2707 ranges = &layout->spacing;
2708 break;
2710 ranges = &layout->typographies;
2711 break;
2712 default:
2713 FIXME("unknown attr kind %d\n", attr);
2714 return E_FAIL;
2715 }
2716
2717 /* If new range is completely within existing range, split existing range in two */
2718 if ((outer = find_outer_range(ranges, &value->range))) {
2719
2720 /* no need to add same range */
2722 return S_OK;
2723
2724 /* for matching range bounds just replace data */
2725 if (is_same_text_range(&outer->range, &value->range)) {
2727 goto done;
2728 }
2729
2730 /* add new range to the left */
2731 if (value->range.startPosition == outer->range.startPosition) {
2733 if (!left) return E_OUTOFMEMORY;
2734
2736 list_add_before(&outer->entry, &left->entry);
2737 outer->range.startPosition += value->range.length;
2738 outer->range.length -= value->range.length;
2739 goto done;
2740 }
2741
2742 /* add new range to the right */
2743 if (value->range.startPosition + value->range.length == outer->range.startPosition + outer->range.length) {
2745 if (!right) return E_OUTOFMEMORY;
2746
2748 list_add_after(&outer->entry, &right->entry);
2749 outer->range.length -= value->range.length;
2750 goto done;
2751 }
2752
2753 r.startPosition = value->range.startPosition + value->range.length;
2754 r.length = outer->range.length + outer->range.startPosition - r.startPosition;
2755
2756 /* right part */
2758 /* new range in the middle */
2760 if (!right || !cur) {
2763 return E_OUTOFMEMORY;
2764 }
2765
2766 /* reuse container range as a left part */
2767 outer->range.length = value->range.startPosition - outer->range.startPosition;
2768
2769 /* new part */
2771
2772 list_add_after(&outer->entry, &cur->entry);
2773 list_add_after(&cur->entry, &right->entry);
2774
2776 return S_OK;
2777 }
2778
2779 /* Now it's only possible that given range contains some existing ranges, fully or partially.
2780 Update all of them. */
2781 left = get_layout_range_header_by_pos(ranges, value->range.startPosition);
2782 if (left->range.startPosition == value->range.startPosition)
2784 else /* need to split */ {
2785 r.startPosition = value->range.startPosition;
2786 r.length = left->range.length - value->range.startPosition + left->range.startPosition;
2787 left->range.length -= r.length;
2790 list_add_after(&left->entry, &cur->entry);
2791 }
2792 cur = LIST_ENTRY(list_next(ranges, &left->entry), struct layout_range_header, entry);
2793
2794 /* for all existing ranges covered by new one update value */
2795 while (cur && is_in_layout_range(&value->range, &cur->range)) {
2796 changed |= set_layout_range_attrval(cur, attr, value);
2797 cur = LIST_ENTRY(list_next(ranges, &cur->entry), struct layout_range_header, entry);
2798 }
2799
2800 /* it's possible rightmost range intersects */
2801 if (cur && (cur->range.startPosition < value->range.startPosition + value->range.length)) {
2802 r.startPosition = cur->range.startPosition;
2803 r.length = value->range.startPosition + value->range.length - cur->range.startPosition;
2806 cur->range.startPosition += left->range.length;
2807 cur->range.length -= left->range.length;
2808 list_add_before(&cur->entry, &left->entry);
2809 }
2810
2811done:
2812 if (changed) {
2813 struct list *next, *i;
2814
2816 i = list_head(ranges);
2817 while ((next = list_next(ranges, i))) {
2818 struct layout_range_header *next_range = LIST_ENTRY(next, struct layout_range_header, entry);
2819
2821 if (is_same_layout_attributes(cur, next_range)) {
2822 /* remove similar range */
2823 cur->range.length += next_range->range.length;
2825 free_layout_range(next_range);
2826 }
2827 else
2828 i = list_next(ranges, i);
2829 }
2830 }
2831
2832 return S_OK;
2833}
2834
2836{
2837 const WCHAR *str;
2838
2839 switch (kind) {
2841 str = range->locale;
2842 break;
2844 str = range->fontfamily;
2845 break;
2846 default:
2847 str = NULL;
2848 }
2849
2850 return str;
2851}
2852
2854 UINT32 position, UINT32 *length, DWRITE_TEXT_RANGE *r)
2855{
2856 struct layout_range *range;
2857 const WCHAR *str;
2858
2859 range = get_layout_range_by_pos(layout, position);
2860 if (!range) {
2861 *length = 0;
2862 return S_OK;
2863 }
2864
2866 *length = wcslen(str);
2867 return return_range(&range->h, r);
2868}
2869
2872{
2873 struct layout_range *range;
2874 const WCHAR *str;
2875
2876 if (length == 0)
2877 return E_INVALIDARG;
2878
2879 ret[0] = 0;
2880 range = get_layout_range_by_pos(layout, position);
2881 if (!range)
2882 return E_INVALIDARG;
2883
2885 if (length < wcslen(str) + 1)
2887
2888 wcscpy(ret, str);
2889 return return_range(&range->h, r);
2890}
2891
2893{
2894 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
2895
2896 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
2897
2898 *obj = NULL;
2899
2900 if (IsEqualIID(riid, &IID_IDWriteTextLayout4) ||
2901 IsEqualIID(riid, &IID_IDWriteTextLayout3) ||
2902 IsEqualIID(riid, &IID_IDWriteTextLayout2) ||
2903 IsEqualIID(riid, &IID_IDWriteTextLayout1) ||
2904 IsEqualIID(riid, &IID_IDWriteTextLayout) ||
2906 {
2907 *obj = iface;
2908 }
2909 else if (IsEqualIID(riid, &IID_IDWriteTextFormat3) ||
2910 IsEqualIID(riid, &IID_IDWriteTextFormat2) ||
2911 IsEqualIID(riid, &IID_IDWriteTextFormat1) ||
2912 IsEqualIID(riid, &IID_IDWriteTextFormat))
2913 {
2914 *obj = &layout->IDWriteTextFormat3_iface;
2915 }
2916
2917 if (*obj) {
2918 IDWriteTextLayout4_AddRef(iface);
2919 return S_OK;
2920 }
2921
2922 WARN("%s not implemented.\n", debugstr_guid(riid));
2923
2924 return E_NOINTERFACE;
2925}
2926
2928{
2929 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
2931
2932 TRACE("%p, refcount %lu.\n", iface, refcount);
2933
2934 return refcount;
2935}
2936
2938{
2939 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
2941
2942 TRACE("%p, refcount %lu.\n", iface, refcount);
2943
2944 if (!refcount)
2945 {
2946 IDWriteFactory7_Release(layout->factory);
2947 if (layout->system_collection)
2948 IDWriteFontCollection_Release(layout->system_collection);
2950 free_layout_eruns(layout);
2951 free_layout_runs(layout);
2952 release_format_data(&layout->format);
2953 free(layout->nominal_breakpoints);
2954 free(layout->actual_breakpoints);
2955 free(layout->clustermetrics);
2956 free(layout->clusters);
2957 free(layout->lines);
2958 free(layout->str);
2959 free(layout);
2960 }
2961
2962 return refcount;
2963}
2964
2966{
2967 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
2968 return IDWriteTextFormat3_SetTextAlignment(&layout->IDWriteTextFormat3_iface, alignment);
2969}
2970
2973{
2974 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
2975 return IDWriteTextFormat3_SetParagraphAlignment(&layout->IDWriteTextFormat3_iface, alignment);
2976}
2977
2979{
2980 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
2981 return IDWriteTextFormat3_SetWordWrapping(&layout->IDWriteTextFormat3_iface, wrapping);
2982}
2983
2986{
2987 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
2988 return IDWriteTextFormat3_SetReadingDirection(&layout->IDWriteTextFormat3_iface, direction);
2989}
2990
2992{
2993 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
2994 return IDWriteTextFormat3_SetFlowDirection(&layout->IDWriteTextFormat3_iface, direction);
2995}
2996
2998{
2999 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3000 return IDWriteTextFormat3_SetIncrementalTabStop(&layout->IDWriteTextFormat3_iface, tabstop);
3001}
3002
3004 IDWriteInlineObject *trimming_sign)
3005{
3006 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3007 return IDWriteTextFormat3_SetTrimming(&layout->IDWriteTextFormat3_iface, trimming, trimming_sign);
3008}
3009
3011 FLOAT line_spacing, FLOAT baseline)
3012{
3013 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3014 return IDWriteTextFormat1_SetLineSpacing((IDWriteTextFormat1 *)&layout->IDWriteTextFormat3_iface, spacing,
3015 line_spacing, baseline);
3016}
3017
3019{
3020 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3021 return IDWriteTextFormat3_GetTextAlignment(&layout->IDWriteTextFormat3_iface);
3022}
3023
3025{
3026 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3027 return IDWriteTextFormat3_GetParagraphAlignment(&layout->IDWriteTextFormat3_iface);
3028}
3029
3031{
3032 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3033 return IDWriteTextFormat3_GetWordWrapping(&layout->IDWriteTextFormat3_iface);
3034}
3035
3037{
3038 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3039 return IDWriteTextFormat3_GetReadingDirection(&layout->IDWriteTextFormat3_iface);
3040}
3041
3043{
3044 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3045 return IDWriteTextFormat3_GetFlowDirection(&layout->IDWriteTextFormat3_iface);
3046}
3047
3049{
3050 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3051 return IDWriteTextFormat3_GetIncrementalTabStop(&layout->IDWriteTextFormat3_iface);
3052}
3053
3055 IDWriteInlineObject **trimming_sign)
3056{
3057 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3058 return IDWriteTextFormat3_GetTrimming(&layout->IDWriteTextFormat3_iface, options, trimming_sign);
3059}
3060
3063{
3064 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3065 return IDWriteTextFormat_GetLineSpacing((IDWriteTextFormat *)&layout->IDWriteTextFormat3_iface, method,
3066 spacing, baseline);
3067}
3068
3070{
3071 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3072 return IDWriteTextFormat3_GetFontCollection(&layout->IDWriteTextFormat3_iface, collection);
3073}
3074
3076{
3077 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3078 return IDWriteTextFormat3_GetFontFamilyNameLength(&layout->IDWriteTextFormat3_iface);
3079}
3080
3082{
3083 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3084 return IDWriteTextFormat3_GetFontFamilyName(&layout->IDWriteTextFormat3_iface, name, size);
3085}
3086
3088{
3089 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3090 return IDWriteTextFormat3_GetFontWeight(&layout->IDWriteTextFormat3_iface);
3091}
3092
3094{
3095 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3096 return IDWriteTextFormat3_GetFontStyle(&layout->IDWriteTextFormat3_iface);
3097}
3098
3100{
3101 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3102 return IDWriteTextFormat3_GetFontStretch(&layout->IDWriteTextFormat3_iface);
3103}
3104
3106{
3107 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3108 return IDWriteTextFormat3_GetFontSize(&layout->IDWriteTextFormat3_iface);
3109}
3110
3112{
3113 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3114 return IDWriteTextFormat3_GetLocaleNameLength(&layout->IDWriteTextFormat3_iface);
3115}
3116
3118{
3119 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3120 return IDWriteTextFormat3_GetLocaleName(&layout->IDWriteTextFormat3_iface, name, size);
3121}
3122
3124{
3125 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3126 BOOL changed;
3127
3128 TRACE("%p, %.8e.\n", iface, maxWidth);
3129
3130 if (maxWidth < 0.0f)
3131 return E_INVALIDARG;
3132
3133 changed = layout->metrics.layoutWidth != maxWidth;
3134 layout->metrics.layoutWidth = maxWidth;
3135
3136 if (changed)
3138 return S_OK;
3139}
3140
3142{
3143 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3144 BOOL changed;
3145
3146 TRACE("%p, %.8e.\n", iface, maxHeight);
3147
3148 if (maxHeight < 0.0f)
3149 return E_INVALIDARG;
3150
3151 changed = layout->metrics.layoutHeight != maxHeight;
3152 layout->metrics.layoutHeight = maxHeight;
3153
3154 if (changed)
3156 return S_OK;
3157}
3158
3161{
3162 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3164
3165 TRACE("%p, %p, %s.\n", iface, collection, debugstr_range(&range));
3166
3167 value.range = range;
3168 value.u.collection = collection;
3170}
3171
3174{
3175 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3177
3178 TRACE("%p, %s, %s.\n", iface, debugstr_w(name), debugstr_range(&range));
3179
3180 if (!name)
3181 return E_INVALIDARG;
3182
3183 value.range = range;
3184 value.u.fontfamily = name;
3186}
3187
3190{
3191 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3193
3194 TRACE("%p, %d, %s.\n", iface, weight, debugstr_range(&range));
3195
3197 return E_INVALIDARG;
3198
3199 value.range = range;
3200 value.u.weight = weight;
3202}
3203
3206{
3207 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3209
3210 TRACE("%p, %d, %s.\n", iface, style, debugstr_range(&range));
3211
3213 return E_INVALIDARG;
3214
3215 value.range = range;
3216 value.u.style = style;
3218}
3219
3222{
3223 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3225
3226 TRACE("%p, %d, %s.\n", iface, stretch, debugstr_range(&range));
3227
3229 return E_INVALIDARG;
3230
3231 value.range = range;
3232 value.u.stretch = stretch;
3234}
3235
3237{
3238 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3240
3241 TRACE("%p, %.8e, %s.\n", iface, size, debugstr_range(&range));
3242
3243 if (size <= 0.0f)
3244 return E_INVALIDARG;
3245
3246 value.range = range;
3247 value.u.fontsize = size;
3249}
3250
3252{
3253 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3255
3256 TRACE("%p, %d, %s.\n", iface, underline, debugstr_range(&range));
3257
3258 value.range = range;
3259 value.u.underline = underline;
3261}
3262
3265{
3266 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3268
3269 TRACE("%p, %d, %s.\n", iface, strikethrough, debugstr_range(&range));
3270
3271 value.range = range;
3272 value.u.strikethrough = strikethrough;
3274}
3275
3278{
3279 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3281
3282 TRACE("%p, %p, %s.\n", iface, effect, debugstr_range(&range));
3283
3284 value.range = range;
3285 value.u.effect = effect;
3287}
3288
3291{
3292 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3294
3295 TRACE("%p, %p, %s.\n", iface, object, debugstr_range(&range));
3296
3297 value.range = range;
3298 value.u.object = object;
3300}
3301
3304{
3305 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3307
3308 TRACE("%p, %p, %s.\n", iface, typography, debugstr_range(&range));
3309
3310 value.range = range;
3311 value.u.typography = typography;
3313}
3314
3317{
3318 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3320
3321 TRACE("%p, %s, %s.\n", iface, debugstr_w(locale), debugstr_range(&range));
3322
3324 return E_INVALIDARG;
3325
3326 value.range = range;
3327 value.u.locale = locale;
3329}
3330
3332{
3333 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3334
3335 TRACE("%p.\n", iface);
3336
3337 return layout->metrics.layoutWidth;
3338}
3339
3341{
3342 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3343
3344 TRACE("%p.\n", iface);
3345
3346 return layout->metrics.layoutHeight;
3347}
3348
3351{
3352 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3353 struct layout_range *range;
3354
3355 TRACE("%p, %u, %p, %p.\n", iface, position, collection, r);
3356
3357 range = get_layout_range_by_pos(layout, position);
3358 *collection = range->collection;
3359 if (*collection)
3360 IDWriteFontCollection_AddRef(*collection);
3361
3362 return return_range(&range->h, r);
3363}
3364
3366 UINT32 position, UINT32 *length, DWRITE_TEXT_RANGE *r)
3367{
3368 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3369
3370 TRACE("%p, %d, %p, %p.\n", iface, position, length, r);
3371
3373}
3374
3377{
3378 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3379
3380 TRACE("%p, %u, %p, %u, %p.\n", iface, position, name, length, r);
3381
3383}
3384
3387{
3388 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3389 struct layout_range *range;
3390
3391 TRACE("%p, %u, %p, %p.\n", iface, position, weight, r);
3392
3393 range = get_layout_range_by_pos(layout, position);
3394 *weight = range->weight;
3395
3396 return return_range(&range->h, r);
3397}
3398
3401{
3402 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3403 struct layout_range *range;
3404
3405 TRACE("%p, %u, %p, %p.\n", iface, position, style, r);
3406
3407 range = get_layout_range_by_pos(layout, position);
3408 *style = range->style;
3409 return return_range(&range->h, r);
3410}
3411
3414{
3415 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3416 struct layout_range *range;
3417
3418 TRACE("%p, %u, %p, %p.\n", iface, position, stretch, r);
3419
3420 range = get_layout_range_by_pos(layout, position);
3421 *stretch = range->stretch;
3422 return return_range(&range->h, r);
3423}
3424
3426 UINT32 position, FLOAT *size, DWRITE_TEXT_RANGE *r)
3427{
3428 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3429 struct layout_range *range;
3430
3431 TRACE("%p, %u, %p, %p.\n", iface, position, size, r);
3432
3433 range = get_layout_range_by_pos(layout, position);
3434 *size = range->fontsize;
3435 return return_range(&range->h, r);
3436}
3437
3439 UINT32 position, BOOL *underline, DWRITE_TEXT_RANGE *r)
3440{
3441 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3442 struct layout_range_bool *range;
3443
3444 TRACE("%p, %u, %p, %p.\n", iface, position, underline, r);
3445
3447 *underline = range->value;
3448
3449 return return_range(&range->h, r);
3450}
3451
3453 UINT32 position, BOOL *strikethrough, DWRITE_TEXT_RANGE *r)
3454{
3455 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3456 struct layout_range_bool *range;
3457
3458 TRACE("%p, %u, %p, %p.\n", iface, position, strikethrough, r);
3459
3461 *strikethrough = range->value;
3462
3463 return return_range(&range->h, r);
3464}
3465
3467 UINT32 position, IUnknown **effect, DWRITE_TEXT_RANGE *r)
3468{
3469 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3470 struct layout_range_iface *range;
3471
3472 TRACE("%p, %u, %p, %p.\n", iface, position, effect, r);
3473
3474 range = (struct layout_range_iface *)get_layout_range_header_by_pos(&layout->effects, position);
3475 *effect = range->iface;
3476 if (*effect)
3477 IUnknown_AddRef(*effect);
3478
3479 return return_range(&range->h, r);
3480}
3481
3483 UINT32 position, IDWriteInlineObject **object, DWRITE_TEXT_RANGE *r)
3484{
3485 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3486 struct layout_range *range;
3487
3488 TRACE("%p, %u, %p, %p.\n", iface, position, object, r);
3489
3490 range = get_layout_range_by_pos(layout, position);
3491 *object = range->object;
3492 if (*object)
3493 IDWriteInlineObject_AddRef(*object);
3494
3495 return return_range(&range->h, r);
3496}
3497
3499 UINT32 position, IDWriteTypography** typography, DWRITE_TEXT_RANGE *r)
3500{
3501 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3502 struct layout_range_iface *range;
3503
3504 TRACE("%p, %u, %p, %p.\n", iface, position, typography, r);
3505
3507 *typography = (IDWriteTypography *)range->iface;
3508 if (*typography)
3509 IDWriteTypography_AddRef(*typography);
3510
3511 return return_range(&range->h, r);
3512}
3513
3515 UINT32 position, UINT32 *length, DWRITE_TEXT_RANGE *r)
3516{
3517 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3518
3519 TRACE("%p, %u, %p, %p.\n", iface, position, length, r);
3520
3522}
3523
3526{
3527 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3528
3529 TRACE("%p, %u, %p, %u, %p.\n", iface, position, locale, length, r);
3530
3532}
3533
3534static inline FLOAT renderer_apply_snapping(FLOAT coord, BOOL skiptransform, FLOAT ppdip, FLOAT det,
3535 const DWRITE_MATRIX *m)
3536{
3538
3539 if (!skiptransform) {
3540 /* apply transform */
3541 vec.x = 0.0f;
3542 vec.y = coord * ppdip;
3543
3544 vec2.x = m->m11 * vec.x + m->m21 * vec.y + m->dx;
3545 vec2.y = m->m12 * vec.x + m->m22 * vec.y + m->dy;
3546
3547 /* snap */
3548 vec2.x = floorf(vec2.x + 0.5f);
3549 vec2.y = floorf(vec2.y + 0.5f);
3550
3551 /* apply inverted transform, we don't care about X component at this point */
3552 vec.y = (-m->m12 * vec2.x + m->m11 * vec2.y - (m->m11 * m->dy - m->m12 * m->dx)) / det;
3553 vec.y /= ppdip;
3554 }
3555 else
3556 vec.y = floorf(coord * ppdip + 0.5f) / ppdip;
3557
3558 return vec.y;
3559}
3560
3562 void *context, IDWriteTextRenderer* renderer, FLOAT origin_x, FLOAT origin_y)
3563{
3564 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3565 BOOL disabled = FALSE, skiptransform = FALSE;
3566 struct layout_effective_inline *inlineobject;
3567 struct layout_effective_run *run;
3568 struct layout_strikethrough *s;
3569 struct layout_underline *u;
3570 FLOAT det = 0.0f, ppdip = 0.0f;
3571 DWRITE_MATRIX m = { 0 };
3572 HRESULT hr;
3573
3574 TRACE("%p, %p, %p, %.8e, %.8e.\n", iface, context, renderer, origin_x, origin_y);
3575
3577 if (FAILED(hr))
3578 return hr;
3579
3580 hr = IDWriteTextRenderer_IsPixelSnappingDisabled(renderer, context, &disabled);
3581 if (FAILED(hr))
3582 return hr;
3583
3584 if (!disabled) {
3585 hr = IDWriteTextRenderer_GetPixelsPerDip(renderer, context, &ppdip);
3586 if (FAILED(hr))
3587 return hr;
3588
3589 hr = IDWriteTextRenderer_GetCurrentTransform(renderer, context, &m);
3590 if (FAILED(hr))
3591 return hr;
3592
3593 /* it's only allowed to have a diagonal/antidiagonal transform matrix */
3594 if (ppdip <= 0.0f ||
3595 (m.m11 * m.m22 != 0.0f && (m.m12 != 0.0f || m.m21 != 0.0f)) ||
3596 (m.m12 * m.m21 != 0.0f && (m.m11 != 0.0f || m.m22 != 0.0f)))
3597 disabled = TRUE;
3598 else
3599 skiptransform = should_skip_transform(&m, &det);
3600 }
3601
3602#define SNAP_COORD(x) (disabled ? (x) : renderer_apply_snapping((x), skiptransform, ppdip, det, &m))
3603 /* 1. Regular runs */
3605 {
3606 const struct regular_layout_run *regular = &run->run->u.regular;
3607 UINT32 start_glyph = regular->clustermap[run->start];
3609 DWRITE_GLYPH_RUN glyph_run;
3610
3611 /* Everything but cluster map will be reused from nominal run, as we only need
3612 to adjust some pointers. Cluster map however is rebuilt when effective run is added,
3613 it can't be reused because it has to start with 0 index for each reported run. */
3614 glyph_run = regular->run;
3615 glyph_run.glyphCount = run->glyphcount;
3616
3617 /* fixup glyph data arrays */
3618 glyph_run.glyphIndices += start_glyph;
3619 glyph_run.glyphAdvances += start_glyph;
3620 glyph_run.glyphOffsets += start_glyph;
3621
3622 /* description */
3623 descr = regular->descr;
3624 descr.stringLength = run->length;
3625 descr.string += run->start;
3626 descr.clusterMap = run->clustermap;
3627 descr.textPosition += run->start;
3628
3629 /* return value is ignored */
3630 IDWriteTextRenderer_DrawGlyphRun(renderer,
3631 context,
3632 run->origin.x + run->align_dx + origin_x,
3633 SNAP_COORD(run->origin.y + origin_y),
3634 layout->measuringmode,
3635 &glyph_run,
3636 &descr,
3637 run->effect);
3638 }
3639
3640 /* 2. Inline objects */
3641 LIST_FOR_EACH_ENTRY(inlineobject, &layout->inlineobjects, struct layout_effective_inline, entry)
3642 {
3643 IDWriteTextRenderer_DrawInlineObject(renderer,
3644 context,
3645 inlineobject->origin.x + inlineobject->align_dx + origin_x,
3646 SNAP_COORD(inlineobject->origin.y + origin_y),
3647 inlineobject->object,
3648 inlineobject->is_sideways,
3649 inlineobject->is_rtl,
3650 inlineobject->effect);
3651 }
3652
3653 /* 3. Underlines */
3655 {
3656 IDWriteTextRenderer_DrawUnderline(renderer,
3657 context,
3658 /* horizontal underline always grows from left to right, width is always added to origin regardless of run direction */
3659 (is_run_rtl(u->run) ? u->run->origin.x - u->run->width : u->run->origin.x) + u->run->align_dx + origin_x,
3660 SNAP_COORD(u->run->origin.y + origin_y),
3661 &u->u,
3662 u->run->effect);
3663 }
3664
3665 /* 4. Strikethrough */
3667 {
3668 IDWriteTextRenderer_DrawStrikethrough(renderer,
3669 context,
3670 s->run->origin.x + s->run->align_dx + origin_x,
3671 SNAP_COORD(s->run->origin.y + origin_y),
3672 &s->s,
3673 s->run->effect);
3674 }
3675#undef SNAP_COORD
3676
3677 return S_OK;
3678}
3679
3682{
3683 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3684 unsigned int line_count;
3685 HRESULT hr;
3686 size_t i;
3687
3688 TRACE("%p, %p, %u, %p.\n", iface, metrics, max_count, count);
3689
3691 return hr;
3692
3693 if (metrics)
3694 {
3695 line_count = min(max_count, layout->metrics.lineCount);
3696 for (i = 0; i < line_count; ++i)
3697 memcpy(&metrics[i], &layout->lines[i].metrics, sizeof(*metrics));
3698 }
3699
3700 *count = layout->metrics.lineCount;
3702}
3703
3705{
3706 return layout_compute_effective_runs(layout);
3707}
3708
3710{
3711 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3712 HRESULT hr;
3713
3714 TRACE("%p, %p.\n", iface, metrics);
3715
3716 hr = layout_update_metrics(layout);
3717 if (hr == S_OK)
3718 memcpy(metrics, &layout->metrics, sizeof(*metrics));
3719
3720 return hr;
3721}
3722
3724{
3725 rect->left += x;
3726 rect->right += x;
3727 rect->top += y;
3728 rect->bottom += y;
3729}
3730
3732{
3733 return ((rect->left >= rect->right) || (rect->top >= rect->bottom));
3734}
3735
3737{
3738 if (d2d_rect_is_empty(dst)) {
3739 if (d2d_rect_is_empty(src)) {
3740 dst->left = dst->right = dst->top = dst->bottom = 0.0f;
3741 return;
3742 }
3743 else
3744 *dst = *src;
3745 }
3746 else {
3747 if (!d2d_rect_is_empty(src)) {
3748 dst->left = min(dst->left, src->left);
3749 dst->right = max(dst->right, src->right);
3750 dst->top = min(dst->top, src->top);
3751 dst->bottom = max(dst->bottom, src->bottom);
3752 }
3753 }
3754}
3755
3757{
3758 const struct regular_layout_run *regular = &run->run->u.regular;
3759 UINT32 start_glyph = regular->clustermap[run->start];
3760 D2D1_POINT_2F baseline_origin = { 0 }, *origins;
3761 DWRITE_GLYPH_RUN glyph_run;
3762 unsigned int i;
3763 HRESULT hr;
3764
3765 if (run->bbox.top == run->bbox.bottom)
3766 {
3767 struct dwrite_glyphbitmap glyph_bitmap;
3768 RECT *bbox;
3769
3770 glyph_run = regular->run;
3771 glyph_run.glyphCount = run->glyphcount;
3772 glyph_run.glyphIndices = &regular->run.glyphIndices[start_glyph];
3773 glyph_run.glyphAdvances = &regular->run.glyphAdvances[start_glyph];
3774 glyph_run.glyphOffsets = &regular->run.glyphOffsets[start_glyph];
3775
3776 memset(&glyph_bitmap, 0, sizeof(glyph_bitmap));
3777 glyph_bitmap.simulations = IDWriteFontFace_GetSimulations(glyph_run.fontFace);
3778 glyph_bitmap.emsize = glyph_run.fontEmSize;
3779
3780 bbox = &glyph_bitmap.bbox;
3781
3782 if (!(origins = calloc(glyph_run.glyphCount, sizeof(*origins))))
3783 return;
3784
3785 if (FAILED(hr = compute_glyph_origins(&glyph_run, layout->measuringmode, baseline_origin, &layout->transform, origins)))
3786 {
3787 WARN("Failed to compute glyph origins, hr %#lx.\n", hr);
3788 free(origins);
3789 return;
3790 }
3791
3792 for (i = 0; i < glyph_run.glyphCount; ++i)
3793 {
3794 D2D1_RECT_F glyph_bbox;
3795
3796 glyph_bitmap.glyph = glyph_run.glyphIndices[i];
3797 dwrite_fontface_get_glyph_bbox(glyph_run.fontFace, &glyph_bitmap);
3798
3799 glyph_bbox.left = bbox->left;
3800 glyph_bbox.top = bbox->top;
3801 glyph_bbox.right = bbox->right;
3802 glyph_bbox.bottom = bbox->bottom;
3803
3804 d2d_rect_offset(&glyph_bbox, origins[i].x, origins[i].y);
3805 d2d_rect_union(&run->bbox, &glyph_bbox);
3806 }
3807
3808 free(origins);
3809 }
3810
3811 *bbox = run->bbox;
3812 d2d_rect_offset(bbox, run->origin.x + run->align_dx, run->origin.y);
3813}
3814
3816{
3817 DWRITE_OVERHANG_METRICS overhang_metrics = { 0 };
3819 HRESULT hr;
3820
3821 if (FAILED(hr = IDWriteInlineObject_GetMetrics(run->object, &metrics))) {
3822 WARN("Failed to get inline object metrics, hr %#lx.\n", hr);
3823 memset(bbox, 0, sizeof(*bbox));
3824 return;
3825 }
3826
3827 bbox->left = run->origin.x + run->align_dx;
3828 bbox->right = bbox->left + metrics.width;
3829 bbox->top = run->origin.y;
3830 bbox->bottom = bbox->top + metrics.height;
3831
3832 IDWriteInlineObject_GetOverhangMetrics(run->object, &overhang_metrics);
3833
3834 bbox->left -= overhang_metrics.left;
3835 bbox->right += overhang_metrics.right;
3836 bbox->top -= overhang_metrics.top;
3837 bbox->bottom += overhang_metrics.bottom;
3838}
3839
3841 DWRITE_OVERHANG_METRICS *overhangs)
3842{
3843 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3844 struct layout_effective_inline *inline_run;
3845 struct layout_effective_run *run;
3846 D2D1_RECT_F bbox = { 0 };
3847 HRESULT hr;
3848
3849 TRACE("%p, %p.\n", iface, overhangs);
3850
3851 memset(overhangs, 0, sizeof(*overhangs));
3852
3853 if (!(layout->recompute & RECOMPUTE_OVERHANGS))
3854 {
3855 *overhangs = layout->overhangs;
3856 return S_OK;
3857 }
3858
3860 if (FAILED(hr))
3861 return hr;
3862
3864 {
3865 D2D1_RECT_F run_bbox;
3866
3867 layout_get_erun_bbox(layout, run, &run_bbox);
3868 d2d_rect_union(&bbox, &run_bbox);
3869 }
3870
3871 LIST_FOR_EACH_ENTRY(inline_run, &layout->inlineobjects, struct layout_effective_inline, entry)
3872 {
3873 D2D1_RECT_F object_bbox;
3874
3875 layout_get_inlineobj_bbox(inline_run, &object_bbox);
3876 d2d_rect_union(&bbox, &object_bbox);
3877 }
3878
3879 /* Deltas from layout box. */
3880 layout->overhangs.left = -bbox.left;
3881 layout->overhangs.top = -bbox.top;
3882 layout->overhangs.right = bbox.right - layout->metrics.layoutWidth;
3883 layout->overhangs.bottom = bbox.bottom - layout->metrics.layoutHeight;
3884 layout->recompute &= ~RECOMPUTE_OVERHANGS;
3885
3886 *overhangs = layout->overhangs;
3887
3888 return S_OK;
3889}
3890
3893{
3894 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3895 HRESULT hr;
3896
3897 TRACE("%p, %p, %u, %p.\n", iface, metrics, max_count, count);
3898
3899 hr = layout_compute(layout);
3900 if (FAILED(hr))
3901 return hr;
3902
3903 if (metrics)
3905
3906 *count = layout->cluster_count;
3908}
3909
3911{
3912 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3913 UINT32 start;
3914 FLOAT width;
3915 HRESULT hr;
3916
3917 TRACE("%p, %p.\n", iface, min_width);
3918
3919 if (!min_width)
3920 return E_INVALIDARG;
3921
3922 if (!(layout->recompute & RECOMPUTE_MINIMAL_WIDTH))
3923 goto width_done;
3924
3925 *min_width = 0.0f;
3926 hr = layout_compute(layout);
3927 if (FAILED(hr))
3928 return hr;
3929
3930 /* Find widest word without emergency breaking between clusters, trailing whitespaces
3931 preceding breaking point do not contribute to word width. */
3932 for (start = 0; start < layout->cluster_count;)
3933 {
3934 UINT32 end = start, j, next;
3935
3936 /* Last cluster always could be wrapped after. */
3937 while (!layout->clustermetrics[end].canWrapLineAfter)
3938 end++;
3939 /* make is so current cluster range that we can wrap after is [start,end) */
3940 end++;
3941
3942 next = end;
3943
3944 /* Ignore trailing whitespace clusters, in case of single space range will
3945 be reduced to empty range, or [start,start+1). */
3946 while (end > start && layout->clustermetrics[end-1].isWhitespace)
3947 end--;
3948
3949 /* check if cluster range exceeds last minimal width */
3950 width = 0.0f;
3951 for (j = start; j < end; j++)
3952 width += layout->clustermetrics[j].width;
3953
3954 start = next;
3955
3956 if (width > layout->minwidth)
3957 layout->minwidth = width;
3958 }
3959 layout->recompute &= ~RECOMPUTE_MINIMAL_WIDTH;
3960
3961width_done:
3962 *min_width = layout->minwidth;
3963 return S_OK;
3964}
3965
3967 FLOAT pointX, FLOAT pointY, BOOL* is_trailinghit, BOOL* is_inside, DWRITE_HIT_TEST_METRICS *metrics)
3968{
3969 FIXME("%p, %.8e, %.8e, %p, %p, %p): stub\n", iface, pointX, pointY, is_trailinghit, is_inside, metrics);
3970
3971 return E_NOTIMPL;
3972}
3973
3975 UINT32 textPosition, BOOL is_trailinghit, FLOAT *pointX, FLOAT *pointY, DWRITE_HIT_TEST_METRICS *metrics)
3976{
3977 FIXME("%p, %u, %d, %p, %p, %p): stub\n", iface, textPosition, is_trailinghit, pointX, pointY, metrics);
3978
3979 return E_NOTIMPL;
3980}
3981
3983 UINT32 textPosition, UINT32 textLength, FLOAT originX, FLOAT originY,
3984 DWRITE_HIT_TEST_METRICS *metrics, UINT32 max_metricscount, UINT32* actual_metricscount)
3985{
3986 FIXME("%p, %u, %u, %f, %f, %p, %u, %p): stub\n", iface, textPosition, textLength, originX, originY, metrics,
3987 max_metricscount, actual_metricscount);
3988
3989 return E_NOTIMPL;
3990}
3991
3994{
3995 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
3997
3998 TRACE("%p, %d, %s.\n", iface, is_pairkerning_enabled, debugstr_range(&range));
3999
4000 value.range = range;
4001 value.u.pair_kerning = !!is_pairkerning_enabled;
4003}
4004
4006 BOOL *is_pairkerning_enabled, DWRITE_TEXT_RANGE *r)
4007{
4008 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
4009 struct layout_range *range;
4010
4011 TRACE("%p, %u, %p, %p.\n", iface, position, is_pairkerning_enabled, r);
4012
4013 range = get_layout_range_by_pos(layout, position);
4014 *is_pairkerning_enabled = range->pair_kerning;
4015
4016 return return_range(&range->h, r);
4017}
4018
4020 FLOAT min_advance, DWRITE_TEXT_RANGE range)
4021{
4022 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
4024
4025 TRACE("%p, %.8e, %.8e, %.8e, %s.\n", iface, leading, trailing, min_advance, debugstr_range(&range));
4026
4027 if (min_advance < 0.0f)
4028 return E_INVALIDARG;
4029
4030 value.range = range;
4031 value.u.spacing.leading = leading;
4032 value.u.spacing.trailing = trailing;
4033 value.u.spacing.min_advance = min_advance;
4035}
4036
4039{
4040 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
4042
4043 TRACE("%p, %u, %p, %p, %p, %p.\n", iface, position, leading, trailing, min_advance, r);
4044
4045 range = (struct layout_range_spacing *)get_layout_range_header_by_pos(&layout->spacing, position);
4046 *leading = range->leading;
4047 *trailing = range->trailing;
4048 *min_advance = range->min_advance;
4049
4050 return return_range(&range->h, r);
4051}
4052
4054{
4055 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
4056 HRESULT hr;
4057
4058 TRACE("%p, %p.\n", iface, metrics);
4059
4060 if (SUCCEEDED(hr = layout_update_metrics(layout)))
4061 *metrics = layout->metrics;
4062
4063 return hr;
4064}
4065
4068{
4069 BOOL changed;
4070 HRESULT hr;
4071
4072 if (FAILED(hr = format_set_vertical_orientation(&layout->format, orientation, &changed)))
4073 return hr;
4074
4075 if (changed)
4077
4078 return S_OK;
4079}
4080
4083{
4084 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
4085
4086 TRACE("%p, %d.\n", iface, orientation);
4087
4088 return layout_set_vertical_orientation(layout, orientation);
4089}
4090
4092{
4093 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
4094
4095 TRACE("%p.\n", iface);
4096
4097 return layout->format.vertical_orientation;
4098}
4099
4101{
4102 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
4103
4104 TRACE("%p, %d.\n", iface, lastline_wrapping_enabled);
4105
4106 return IDWriteTextFormat3_SetLastLineWrapping(&layout->IDWriteTextFormat3_iface, lastline_wrapping_enabled);
4107}
4108
4110{
4111 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
4112
4113 TRACE("%p.\n", iface);
4114
4115 return IDWriteTextFormat3_GetLastLineWrapping(&layout->IDWriteTextFormat3_iface);
4116}
4117
4120{
4121 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
4122
4123 TRACE("%p, %d.\n", iface, alignment);
4124
4125 return IDWriteTextFormat3_SetOpticalAlignment(&layout->IDWriteTextFormat3_iface, alignment);
4126}
4127
4129{
4130 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
4131
4132 TRACE("%p.\n", iface);
4133
4134 return IDWriteTextFormat3_GetOpticalAlignment(&layout->IDWriteTextFormat3_iface);
4135}
4136
4138{
4139 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
4140
4141 TRACE("%p, %p.\n", iface, fallback);
4142
4143 return format_set_fontfallback(&layout->format, fallback);
4144}
4145
4147{
4148 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
4149
4150 TRACE("%p, %p.\n", iface, fallback);
4151
4152 return format_get_fontfallback(&layout->format, fallback);
4153}
4154
4156{
4157 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
4158
4159 TRACE("%p.\n", iface);
4160
4162 return S_OK;
4163}
4164
4166{
4167 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
4168 BOOL changed;
4169 HRESULT hr;
4170
4171 TRACE("%p, %p.\n", iface, spacing);
4172
4173 hr = format_set_linespacing(&layout->format, spacing, &changed);
4174 if (FAILED(hr))
4175 return hr;
4176
4177 if (changed)
4178 {
4179 if (!(layout->recompute & RECOMPUTE_LINES))
4180 {
4181 UINT32 line;
4182
4183 for (line = 0; line < layout->metrics.lineCount; line++)
4185
4187 }
4188
4189 layout->recompute |= RECOMPUTE_OVERHANGS;
4190 }
4191
4192 return S_OK;
4193}
4194
4196{
4197 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
4198
4199 TRACE("%p, %p.\n", iface, spacing);
4200
4201 *spacing = layout->format.spacing;
4202 return S_OK;
4203}
4204
4207{
4208 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
4209 unsigned int line_count;
4210 HRESULT hr;
4211 size_t i;
4212
4213 TRACE("%p, %p, %u, %p.\n", iface, metrics, max_count, count);
4214
4216 return hr;
4217
4218 if (metrics)
4219 {
4220 line_count = min(max_count, layout->metrics.lineCount);
4221 for (i = 0; i < line_count; ++i)
4222 metrics[i] = layout->lines[i].metrics;
4223 }
4224
4225 *count = layout->metrics.lineCount;
4227}
4228
4230 DWRITE_FONT_AXIS_VALUE const *axis_values, UINT32 num_values, DWRITE_TEXT_RANGE range)
4231{
4232 FIXME("%p, %p, %u, %s.\n", iface, axis_values, num_values, debugstr_range(&range));
4233
4234 return E_NOTIMPL;
4235}
4236
4238{
4239 FIXME("%p, %u.\n", iface, pos);
4240
4241 return 0;
4242}
4243
4246{
4247 FIXME("%p, %u, %p, %u, %p.\n", iface, pos, values, num_values, range);
4248
4249 return E_NOTIMPL;
4250}
4251
4253{
4254 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
4255
4256 TRACE("%p.\n", iface);
4257
4258 return layout->format.automatic_axes;
4259}
4260
4263{
4264 struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout4(iface);
4265
4266 TRACE("%p, %d.\n", iface, axes);
4267
4268 if ((unsigned int)axes > DWRITE_AUTOMATIC_FONT_AXES_OPTICAL_SIZE)
4269 return E_INVALIDARG;
4270
4271 layout->format.automatic_axes = axes;
4272 return S_OK;
4273}
4274
4275static const IDWriteTextLayout4Vtbl dwritetextlayoutvtbl =
4276{
4366};
4367
4369{
4370 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4371
4372 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
4373
4374 return IDWriteTextLayout4_QueryInterface(&layout->IDWriteTextLayout4_iface, riid, obj);
4375}
4376
4378{
4379 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4380 return IDWriteTextLayout4_AddRef(&layout->IDWriteTextLayout4_iface);
4381}
4382
4384{
4385 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4386 return IDWriteTextLayout4_Release(&layout->IDWriteTextLayout4_iface);
4387}
4388
4391{
4392 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4393 BOOL changed;
4394 HRESULT hr;
4395
4396 TRACE("%p, %d.\n", iface, alignment);
4397
4398 hr = format_set_textalignment(&layout->format, alignment, &changed);
4399 if (FAILED(hr))
4400 return hr;
4401
4402 if (changed)
4403 {
4404 /* if layout is not ready there's nothing to align */
4405 if (!(layout->recompute & RECOMPUTE_LINES))
4407 layout->recompute |= RECOMPUTE_OVERHANGS;
4408 }
4409
4410 return S_OK;
4411}
4412
4415{
4416 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4417 BOOL changed;
4418 HRESULT hr;
4419
4420 TRACE("%p, %d.\n", iface, alignment);
4421
4422 hr = format_set_paralignment(&layout->format, alignment, &changed);
4423 if (FAILED(hr))
4424 return hr;
4425
4426 if (changed)
4427 {
4428 /* if layout is not ready there's nothing to align */
4429 if (!(layout->recompute & RECOMPUTE_LINES))
4431 layout->recompute |= RECOMPUTE_OVERHANGS;
4432 }
4433
4434 return S_OK;
4435}
4436
4438{
4439 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4440 BOOL changed;
4441 HRESULT hr;
4442
4443 TRACE("%p, %d.\n", iface, wrapping);
4444
4445 hr = format_set_wordwrapping(&layout->format, wrapping, &changed);
4446 if (FAILED(hr))
4447 return hr;
4448
4449 if (changed)
4451
4452 return S_OK;
4453}
4454
4457{
4458 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4459 BOOL changed;
4460 HRESULT hr;
4461
4462 TRACE("%p, %d.\n", iface, direction);
4463
4464 hr = format_set_readingdirection(&layout->format, direction, &changed);
4465 if (FAILED(hr))
4466 return hr;
4467
4468 if (changed)
4470
4471 return S_OK;
4472}
4473
4476{
4477 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4478 BOOL changed;
4479 HRESULT hr;
4480
4481 TRACE("%p, %d.\n", iface, direction);
4482
4483 hr = format_set_flowdirection(&layout->format, direction, &changed);
4484 if (FAILED(hr))
4485 return hr;
4486
4487 if (changed)
4489
4490 return S_OK;
4491}
4492
4494{
4495 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4496
4497 TRACE("%p, %.8e.\n", iface, tabstop);
4498
4499 if (tabstop <= 0.0f)
4500 return E_INVALIDARG;
4501
4502 layout->format.tabstop = tabstop;
4503 return S_OK;
4504}
4505
4507 IDWriteInlineObject *trimming_sign)
4508{
4509 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4510 BOOL changed;
4511 HRESULT hr;
4512
4513 TRACE("%p, %p, %p.\n", iface, trimming, trimming_sign);
4514
4515 hr = format_set_trimming(&layout->format, trimming, trimming_sign, &changed);
4516
4517 if (changed)
4519
4520 return hr;
4521}
4522
4525{
4526 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4528
4529 TRACE("%p, %d, %.8e, %.8e.\n", iface, method, height, baseline);
4530
4531 spacing = layout->format.spacing;
4532 spacing.method = method;
4533 spacing.height = height;
4534 spacing.baseline = baseline;
4535 return IDWriteTextLayout4_SetLineSpacing(&layout->IDWriteTextLayout4_iface, &spacing);
4536}
4537
4539{
4540 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4541
4542 TRACE("%p.\n", iface);
4543
4544 return layout->format.textalignment;
4545}
4546
4548{
4549 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4550
4551 TRACE("%p.\n", iface);
4552
4553 return layout->format.paralign;
4554}
4555
4557{
4558 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4559
4560 TRACE("%p.\n", iface);
4561
4562 return layout->format.wrapping;
4563}
4564
4566{
4567 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4568
4569 TRACE("%p.\n", iface);
4570
4571 return layout->format.readingdir;
4572}
4573
4575{
4576 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4577
4578 TRACE("%p.\n", iface);
4579
4580 return layout->format.flow;
4581}
4582
4584{
4585 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4586
4587 TRACE("%p.\n", iface);
4588
4589 return layout->format.tabstop;
4590}
4591
4593 IDWriteInlineObject **trimming_sign)
4594{
4595 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4596
4597 TRACE("%p, %p, %p.\n", iface, options, trimming_sign);
4598
4599 *options = layout->format.trimming;
4600 *trimming_sign = layout->format.trimmingsign;
4601 if (*trimming_sign)
4602 IDWriteInlineObject_AddRef(*trimming_sign);
4603 return S_OK;
4604}
4605
4608{
4609 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4610
4611 TRACE("%p, %p, %p, %p.\n", iface, method, spacing, baseline);
4612
4613 *method = layout->format.spacing.method;
4614 *spacing = layout->format.spacing.height;
4615 *baseline = layout->format.spacing.baseline;
4616 return S_OK;
4617}
4618
4621{
4622 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4623
4624 TRACE("%p, %p.\n", iface, collection);
4625
4626 *collection = layout->format.collection;
4627 if (*collection)
4628 IDWriteFontCollection_AddRef(*collection);
4629 return S_OK;
4630}
4631
4633{
4634 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4635
4636 TRACE("%p.\n", iface);
4637
4638 return layout->format.family_len;
4639}
4640
4642{
4643 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4644
4645 TRACE("%p, %p, %u.\n", iface, name, size);
4646
4647 if (size <= layout->format.family_len) return E_NOT_SUFFICIENT_BUFFER;
4648 wcscpy(name, layout->format.family_name);
4649 return S_OK;
4650}
4651
4653{
4654 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4655
4656 TRACE("%p.\n", iface);
4657
4658 return layout->format.weight;
4659}
4660
4662{
4663 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4664
4665 TRACE("%p.\n", iface);
4666
4667 return layout->format.style;
4668}
4669
4671{
4672 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4673
4674 TRACE("%p.\n", iface);
4675
4676 return layout->format.stretch;
4677}
4678
4680{
4681 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4682
4683 TRACE("%p.\n", iface);
4684
4685 return layout->format.fontsize;
4686}
4687
4689{
4690 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4691
4692 TRACE("%p.\n", iface);
4693
4694 return layout->format.locale_len;
4695}
4696
4698{
4699 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4700
4701 TRACE("%p, %p, %u.\n", iface, name, size);
4702
4703 if (size <= layout->format.locale_len) return E_NOT_SUFFICIENT_BUFFER;
4704 wcscpy(name, layout->format.locale);
4705 return S_OK;
4706}
4707
4710{
4711 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4712
4713 TRACE("%p, %d.\n", iface, orientation);
4714
4715 return layout_set_vertical_orientation(layout, orientation);
4716}
4717
4719{
4720 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4721
4722 TRACE("%p.\n", iface);
4723
4724 return layout->format.vertical_orientation;
4725}
4726
4728 BOOL lastline_wrapping_enabled)
4729{
4730 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4731
4732 TRACE("%p, %d.\n", iface, lastline_wrapping_enabled);
4733
4734 layout->format.last_line_wrapping = !!lastline_wrapping_enabled;
4735 return S_OK;
4736}
4737
4739{
4740 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4741
4742 TRACE("%p.\n", iface);
4743
4744 return layout->format.last_line_wrapping;
4745}
4746
4749{
4750 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4751
4752 TRACE("%p, %d.\n", iface, alignment);
4753
4755}
4756
4758{
4759 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4760
4761 TRACE("%p.\n", iface);
4762
4763 return layout->format.optical_alignment;
4764}
4765
4767 IDWriteFontFallback *fallback)
4768{
4769 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4770
4771 TRACE("%p, %p.\n", iface, fallback);
4772
4773 return IDWriteTextLayout4_SetFontFallback(&layout->IDWriteTextLayout4_iface, fallback);
4774}
4775
4777 IDWriteFontFallback **fallback)
4778{
4779 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4780
4781 TRACE("%p, %p.\n", iface, fallback);
4782
4783 return IDWriteTextLayout4_GetFontFallback(&layout->IDWriteTextLayout4_iface, fallback);
4784}
4785
4788{
4789 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4790 return IDWriteTextLayout4_SetLineSpacing(&layout->IDWriteTextLayout4_iface, spacing);
4791}
4792
4794{
4795 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4796 return IDWriteTextLayout4_GetLineSpacing(&layout->IDWriteTextLayout4_iface, spacing);
4797}
4798
4800 DWRITE_FONT_AXIS_VALUE const *axis_values, UINT32 num_values)
4801{
4802 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4803
4804 TRACE("%p, %p, %u.\n", iface, axis_values, num_values);
4805
4806 return format_set_font_axisvalues(&layout->format, axis_values, num_values);
4807}
4808
4810{
4811 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4812
4813 TRACE("%p.\n", iface);
4814
4815 return layout->format.axis_values_count;
4816}
4817
4819 DWRITE_FONT_AXIS_VALUE *axis_values, UINT32 num_values)
4820{
4821 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4822
4823 TRACE("%p, %p, %u.\n", iface, axis_values, num_values);
4824
4825 return format_get_font_axisvalues(&layout->format, axis_values, num_values);
4826}
4827
4829{
4830 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4831 return IDWriteTextLayout4_GetAutomaticFontAxes(&layout->IDWriteTextLayout4_iface);
4832}
4833
4836{
4837 struct dwrite_textlayout *layout = impl_from_IDWriteTextFormat3(iface);
4838 return IDWriteTextLayout4_SetAutomaticFontAxes(&layout->IDWriteTextLayout4_iface, axes);
4839}
4840
4841static const IDWriteTextFormat3Vtbl dwritetextformat3_layout_vtbl =
4842{
4886};
4887
4889 REFIID riid, void **obj)
4890{
4891 if (IsEqualIID(riid, &IID_IDWriteTextAnalysisSink1) ||
4892 IsEqualIID(riid, &IID_IDWriteTextAnalysisSink) ||
4894 {
4895 *obj = iface;
4896 IDWriteTextAnalysisSink1_AddRef(iface);
4897 return S_OK;
4898 }
4899
4900 WARN("%s not implemented.\n", debugstr_guid(riid));
4901
4902 *obj = NULL;
4903 return E_NOINTERFACE;
4904}
4905
4907{
4909 return IDWriteTextLayout4_AddRef(&layout->IDWriteTextLayout4_iface);
4910}
4911
4913{
4915 return IDWriteTextLayout4_Release(&layout->IDWriteTextLayout4_iface);
4916}
4917
4919 UINT32 position, UINT32 length, DWRITE_SCRIPT_ANALYSIS const* sa)
4920{
4922 struct layout_run *run;
4923 HRESULT hr;
4924
4925 TRACE("[%u,%u) script=%u:%s\n", position, position + length, sa->script, debugstr_sa_script(sa->script));
4926
4927 if (FAILED(hr = alloc_layout_run(LAYOUT_RUN_REGULAR, position, &run)))
4928 return hr;
4929
4930 run->u.regular.descr.string = &layout->str[position];
4931 run->u.regular.descr.stringLength = length;
4932 run->u.regular.descr.textPosition = position;
4933 run->u.regular.sa = *sa;
4934 list_add_tail(&layout->runs, &run->entry);
4935 return S_OK;
4936}
4937
4939 UINT32 position, UINT32 length, DWRITE_LINE_BREAKPOINT const* breakpoints)
4940{
4942
4943 if (position + length > layout->len)
4944 return E_FAIL;
4945
4946 memcpy(&layout->nominal_breakpoints[position], breakpoints, length*sizeof(DWRITE_LINE_BREAKPOINT));
4947 return S_OK;
4948}
4949
4951 UINT32 length, UINT8 explicitLevel, UINT8 resolvedLevel)
4952{
4954 struct layout_run *cur_run;
4955 HRESULT hr;
4956
4957 TRACE("[%u,%u) %u %u\n", position, position + length, explicitLevel, resolvedLevel);
4958
4959 LIST_FOR_EACH_ENTRY(cur_run, &layout->runs, struct layout_run, entry) {
4960 struct regular_layout_run *cur = &cur_run->u.regular;
4961 struct layout_run *run;
4962
4963 if (cur_run->kind == LAYOUT_RUN_INLINE)
4964 continue;
4965
4966 /* FIXME: levels are reported in a natural forward direction, so start loop from a run we ended on */
4967 if (position < cur->descr.textPosition || position >= cur->descr.textPosition + cur->descr.stringLength)
4968 continue;
4969
4970 /* full hit - just set run level */
4971 if (cur->descr.textPosition == position && cur->descr.stringLength == length) {
4972 cur->run.bidiLevel = resolvedLevel;
4973 break;
4974 }
4975
4976 /* current run is fully covered, move to next one */
4977 if (cur->descr.textPosition == position && cur->descr.stringLength < length) {
4978 cur->run.bidiLevel = resolvedLevel;
4979 position += cur->descr.stringLength;
4980 length -= cur->descr.stringLength;
4981 continue;
4982 }
4983
4984 /* all fully covered runs are processed at this point, reuse existing run for remaining
4985 reported bidi range and add another run for the rest of original one */
4986
4987 if (FAILED(hr = alloc_layout_run(LAYOUT_RUN_REGULAR, position + length, &run)))
4988 return hr;
4989
4990 *run = *cur_run;
4991 run->u.regular.descr.textPosition = position + length;
4992 run->u.regular.descr.stringLength = cur->descr.stringLength - length;
4993 run->u.regular.descr.string = &layout->str[position + length];
4994
4995 /* reduce existing run */
4996 cur->run.bidiLevel = resolvedLevel;
4997 cur->descr.stringLength = length;
4998
4999 list_add_after(&cur_run->entry, &run->entry);
5000 break;
5001 }
5002
5003 return S_OK;
5004}
5005
5007 UINT32 position, UINT32 length, IDWriteNumberSubstitution* substitution)
5008{
5009 return E_NOTIMPL;
5010}
5011
5013 UINT32 position, UINT32 length, DWRITE_GLYPH_ORIENTATION_ANGLE angle, UINT8 adjusted_bidi_level,
5014 BOOL is_sideways, BOOL is_rtl)
5015{
5016 return E_NOTIMPL;
5017}
5018
5019static const IDWriteTextAnalysisSink1Vtbl dwritetextlayoutsinkvtbl = {
5028};
5029
5031 REFIID riid, void **obj)
5032{
5033 if (IsEqualIID(riid, &IID_IDWriteTextAnalysisSource1) ||
5034 IsEqualIID(riid, &IID_IDWriteTextAnalysisSource) ||
5036 {
5037 *obj = iface;
5038 IDWriteTextAnalysisSource1_AddRef(iface);
5039 return S_OK;
5040 }
5041
5042 WARN("%s not implemented.\n", debugstr_guid(riid));
5043
5044 *obj = NULL;
5045 return E_NOINTERFACE;
5046}
5047
5049{
5051 return IDWriteTextLayout4_AddRef(&layout->IDWriteTextLayout4_iface);
5052}
5053
5055{
5057 return IDWriteTextLayout4_Release(&layout->IDWriteTextLayout4_iface);
5058}
5059
5061 UINT32 position, WCHAR const** text, UINT32* text_len)
5062{
5064
5065 TRACE("%p, %u, %p, %p.\n", iface, position, text, text_len);
5066
5067 if (position < layout->text_source.length)
5068 {
5069 *text = &layout->str[position + layout->text_source.offset];
5070 *text_len = layout->text_source.length - position;
5071 }
5072 else
5073 {
5074 *text = NULL;
5075 *text_len = 0;
5076 }
5077
5078 return S_OK;
5079}
5080
5082 UINT32 position, WCHAR const** text, UINT32* text_len)
5083{
5085
5086 TRACE("%p, %u, %p, %p.\n", iface, position, text, text_len);
5087
5088 if (position && position < layout->text_source.length)
5089 {
5090 *text = &layout->str[layout->text_source.offset];
5091 *text_len = position;
5092 }
5093 else
5094 {
5095 *text = NULL;
5096 *text_len = 0;
5097 }
5098
5099 return S_OK;
5100}
5101
5103{
5105 return IDWriteTextLayout4_GetReadingDirection(&layout->IDWriteTextLayout4_iface);
5106}
5107
5109 UINT32 position, UINT32* text_len, WCHAR const** locale)
5110{
5112 struct layout_range *range, *next;
5113 unsigned int end;
5114
5115 if (position < layout->text_source.length)
5116 {
5117 position += layout->text_source.offset;
5118 end = layout->text_source.offset + layout->text_source.length;
5119
5120 range = get_layout_range_by_pos(layout, position);
5121
5122 *locale = range->locale;
5123 *text_len = range->h.range.startPosition + range->h.range.length - position;
5124
5125 next = LIST_ENTRY(list_next(&layout->ranges, &range->h.entry), struct layout_range, h.entry);
5126 while (next && next->h.range.startPosition < end && !wcscmp(range->locale, next->locale))
5127 {
5128 *text_len += next->h.range.length;
5129 next = LIST_ENTRY(list_next(&layout->ranges, &next->h.entry), struct layout_range, h.entry);
5130 }
5131
5132 *text_len = min(*text_len, layout->text_source.length - position);
5133 }
5134 else
5135 {
5136 *locale = NULL;
5137 *text_len = 0;
5138 }
5139
5140 return S_OK;
5141}
5142
5144 UINT32 position, UINT32* text_len, IDWriteNumberSubstitution **substitution)
5145{
5146 FIXME("%u %p %p: stub\n", position, text_len, substitution);
5147 return E_NOTIMPL;
5148}
5149
5151 UINT32 position, UINT32 *length, DWRITE_VERTICAL_GLYPH_ORIENTATION *orientation, UINT8 *bidi_level)
5152{
5153 FIXME("%u %p %p %p: stub\n", position, length, orientation, bidi_level);
5154 return E_NOTIMPL;
5155}
5156
5157static const IDWriteTextAnalysisSource1Vtbl dwritetextlayoutsourcevtbl = {
5167};
5168
5170{
5171 struct dwrite_textformat *textformat;
5172 IDWriteTextFormat1 *format1;
5173 IDWriteTextFormat3 *format3;
5174 UINT32 len;
5175 HRESULT hr;
5176
5177 if ((textformat = unsafe_impl_from_IDWriteTextFormat(format))) {
5178 layout->format = textformat->format;
5179
5180 layout->format.locale = wcsdup(textformat->format.locale);
5181 layout->format.family_name = wcsdup(textformat->format.family_name);
5182 if (!layout->format.locale || !layout->format.family_name)
5183 {
5184 free(layout->format.locale);
5185 free(layout->format.family_name);
5186 return E_OUTOFMEMORY;
5187 }
5188
5189 if (layout->format.trimmingsign)
5190 IDWriteInlineObject_AddRef(layout->format.trimmingsign);
5191 if (layout->format.collection)
5192 IDWriteFontCollection_AddRef(layout->format.collection);
5193 if (layout->format.fallback)
5194 IDWriteFontFallback_AddRef(layout->format.fallback);
5195
5196 return S_OK;
5197 }
5198
5199 layout->format.weight = IDWriteTextFormat_GetFontWeight(format);
5200 layout->format.style = IDWriteTextFormat_GetFontStyle(format);
5201 layout->format.stretch = IDWriteTextFormat_GetFontStretch(format);
5202 layout->format.fontsize= IDWriteTextFormat_GetFontSize(format);
5203 layout->format.tabstop = IDWriteTextFormat_GetIncrementalTabStop(format);
5204 layout->format.textalignment = IDWriteTextFormat_GetTextAlignment(format);
5205 layout->format.paralign = IDWriteTextFormat_GetParagraphAlignment(format);
5206 layout->format.wrapping = IDWriteTextFormat_GetWordWrapping(format);
5207 layout->format.readingdir = IDWriteTextFormat_GetReadingDirection(format);
5208 layout->format.flow = IDWriteTextFormat_GetFlowDirection(format);
5209 hr = IDWriteTextFormat_GetLineSpacing(format, &layout->format.spacing.method,
5210 &layout->format.spacing.height, &layout->format.spacing.baseline);
5211 if (FAILED(hr))
5212 return hr;
5213
5214 hr = IDWriteTextFormat_GetTrimming(format, &layout->format.trimming, &layout->format.trimmingsign);
5215 if (FAILED(hr))
5216 return hr;
5217
5218 /* locale name and length */
5219 len = IDWriteTextFormat_GetLocaleNameLength(format);
5220 if (!(layout->format.locale = malloc((len + 1) * sizeof(WCHAR))))
5221 return E_OUTOFMEMORY;
5222
5223 hr = IDWriteTextFormat_GetLocaleName(format, layout->format.locale, len+1);
5224 if (FAILED(hr))
5225 return hr;
5226 layout->format.locale_len = len;
5227
5228 /* font family name and length */
5229 len = IDWriteTextFormat_GetFontFamilyNameLength(format);
5230 if (!(layout->format.family_name = malloc((len + 1) * sizeof(WCHAR))))
5231 return E_OUTOFMEMORY;
5232
5233 hr = IDWriteTextFormat_GetFontFamilyName(format, layout->format.family_name, len+1);
5234 if (FAILED(hr))
5235 return hr;
5236 layout->format.family_len = len;
5237
5238 hr = IDWriteTextFormat_QueryInterface(format, &IID_IDWriteTextFormat1, (void**)&format1);
5239 if (hr == S_OK)
5240 {
5241 IDWriteTextFormat2 *format2;
5242
5243 layout->format.vertical_orientation = IDWriteTextFormat1_GetVerticalGlyphOrientation(format1);
5244 layout->format.optical_alignment = IDWriteTextFormat1_GetOpticalAlignment(format1);
5245 IDWriteTextFormat1_GetFontFallback(format1, &layout->format.fallback);
5246
5247 if (IDWriteTextFormat1_QueryInterface(format1, &IID_IDWriteTextFormat2, (void**)&format2) == S_OK) {
5248 IDWriteTextFormat2_GetLineSpacing(format2, &layout->format.spacing);
5249 IDWriteTextFormat2_Release(format2);
5250 }
5251
5252 IDWriteTextFormat1_Release(format1);
5253 }
5254
5255 hr = IDWriteTextFormat_QueryInterface(format, &IID_IDWriteTextFormat3, (void **)&format3);
5256 if (hr == S_OK)
5257 {
5258 layout->format.automatic_axes = IDWriteTextFormat3_GetAutomaticFontAxes(format3);
5259 IDWriteTextFormat3_Release(format3);
5260 }
5261
5262 return IDWriteTextFormat_GetFontCollection(format, &layout->format.collection);
5263}
5264
5265static HRESULT init_textlayout(const struct textlayout_desc *desc, struct dwrite_textlayout *layout)
5266{
5267 struct layout_range_header *range, *strike, *underline, *effect, *spacing, *typography;
5268 static const DWRITE_TEXT_RANGE r = { 0, ~0u };
5269 HRESULT hr;
5270
5275 layout->refcount = 1;
5276 layout->len = desc->length;
5278 list_init(&layout->eruns);
5279 list_init(&layout->inlineobjects);
5280 list_init(&layout->underlines);
5281 list_init(&layout->strikethrough);
5282 list_init(&layout->runs);
5283 list_init(&layout->ranges);
5284 list_init(&layout->strike_ranges);
5285 list_init(&layout->underline_ranges);
5286 list_init(&layout->effects);
5287 list_init(&layout->spacing);
5288 list_init(&layout->typographies);
5289 layout->metrics.layoutWidth = desc->max_width;
5290 layout->metrics.layoutHeight = desc->max_height;
5291
5292 layout->str = heap_strdupnW(desc->string, desc->length);
5293 if (desc->length && !layout->str) {
5294 hr = E_OUTOFMEMORY;
5295 goto fail;
5296 }
5297
5298 hr = layout_format_from_textformat(layout, desc->format);
5299 if (FAILED(hr))
5300 goto fail;
5301
5304 underline = alloc_layout_range(layout, &r, LAYOUT_RANGE_UNDERLINE);
5305 effect = alloc_layout_range(layout, &r, LAYOUT_RANGE_EFFECT);
5306 spacing = alloc_layout_range(layout, &r, LAYOUT_RANGE_SPACING);
5307 typography = alloc_layout_range(layout, &r, LAYOUT_RANGE_TYPOGRAPHY);
5308 if (!range || !strike || !effect || !spacing || !typography || !underline) {
5310 free_layout_range(strike);
5311 free_layout_range(underline);
5312 free_layout_range(effect);
5313 free_layout_range(spacing);
5314 free_layout_range(typography);
5315 hr = E_OUTOFMEMORY;
5316 goto fail;
5317 }
5318
5319 layout->measuringmode = desc->is_gdi_compatible ? (desc->use_gdi_natural ? DWRITE_MEASURING_MODE_GDI_NATURAL :
5321 layout->ppdip = desc->ppdip;
5322 layout->transform = desc->transform ? *desc->transform : identity;
5323
5324 layout->factory = desc->factory;
5325 IDWriteFactory7_AddRef(layout->factory);
5326 list_add_head(&layout->ranges, &range->entry);
5327 list_add_head(&layout->strike_ranges, &strike->entry);
5328 list_add_head(&layout->underline_ranges, &underline->entry);
5329 list_add_head(&layout->effects, &effect->entry);
5330 list_add_head(&layout->spacing, &spacing->entry);
5331 list_add_head(&layout->typographies, &typography->entry);
5332
5333 if (FAILED(hr = IDWriteFactory5_GetSystemFontCollection((IDWriteFactory5 *)layout->factory, FALSE,
5335 {
5336 goto fail;
5337 }
5338
5339 return S_OK;
5340
5341fail:
5342 IDWriteTextLayout4_Release(&layout->IDWriteTextLayout4_iface);
5343 return hr;
5344}
5345
5347{
5348 struct dwrite_textlayout *object;
5349 HRESULT hr;
5350
5351 *layout = NULL;
5352
5353 if (desc->max_width < 0.0f || desc->max_height < 0.0f)
5354 return E_INVALIDARG;
5355
5356 if (!desc->format || !desc->string)
5357 return E_INVALIDARG;
5358
5359 if (!(object = calloc(1, sizeof(*object))))
5360 return E_OUTOFMEMORY;
5361
5362 hr = init_textlayout(desc, object);
5363 if (hr == S_OK)
5364 *layout = (IDWriteTextLayout *)&object->IDWriteTextLayout4_iface;
5365
5366 return hr;
5367}
5368
5370{
5371 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
5372
5373 if (IsEqualIID(riid, &IID_IDWriteTypography) || IsEqualIID(riid, &IID_IUnknown)) {
5374 *obj = iface;
5375 IDWriteTypography_AddRef(iface);
5376 return S_OK;
5377 }
5378
5379 WARN("%s not implemented.\n", debugstr_guid(riid));
5380
5381 *obj = NULL;
5382
5383 return E_NOINTERFACE;
5384}
5385
5387{
5388 struct dwrite_typography *typography = impl_from_IDWriteTypography(iface);
5390
5391 TRACE("%p, refcount %ld.\n", iface, refcount);
5392
5393 return refcount;
5394}
5395
5397{
5398 struct dwrite_typography *typography = impl_from_IDWriteTypography(iface);
5400
5401 TRACE("%p, refcount %ld.\n", iface, refcount);
5402
5403 if (!refcount)
5404 {
5405 free(typography->features);
5406 free(typography);
5407 }
5408
5409 return refcount;
5410}
5411
5413{
5414 struct dwrite_typography *typography = impl_from_IDWriteTypography(iface);
5415
5416 TRACE("%p, %s, %u.\n", iface, debugstr_fourcc(feature.nameTag), feature.parameter);
5417
5418 if (!dwrite_array_reserve((void **)&typography->features, &typography->capacity, typography->count + 1,
5419 sizeof(*typography->features)))
5420 {
5421 return E_OUTOFMEMORY;
5422 }
5423
5424 typography->features[typography->count++] = feature;
5425
5426 return S_OK;
5427}
5428
5430{
5431 struct dwrite_typography *typography = impl_from_IDWriteTypography(iface);
5432
5433 TRACE("%p.\n", iface);
5434
5435 return typography->count;
5436}
5437
5440{
5441 struct dwrite_typography *typography = impl_from_IDWriteTypography(iface);
5442
5443 TRACE("%p, %u, %p.\n", iface, index, feature);
5444
5445 if (index >= typography->count)
5446 return E_INVALIDARG;
5447
5448 *feature = typography->features[index];
5449 return S_OK;
5450}
5451
5452static const IDWriteTypographyVtbl dwritetypographyvtbl = {
5459};
5460
5462{
5463 struct dwrite_typography *typography;
5464
5465 *ret = NULL;
5466
5467 if (!(typography = calloc(1, sizeof(*typography))))
5468 return E_OUTOFMEMORY;
5469
5470 typography->IDWriteTypography_iface.lpVtbl = &dwritetypographyvtbl;
5471 typography->refcount = 1;
5472
5473 *ret = &typography->IDWriteTypography_iface;
5474
5475 return S_OK;
5476}
unsigned short UINT16
Definition: actypes.h:129
unsigned char UINT8
Definition: actypes.h:128
static struct sockaddr_in sa
Definition: adnsresfilter.c:69
_Check_return_ _Ret_maybenull_ _In_ size_t alignment
Definition: align.cpp:48
HRESULT create_matching_font(IDWriteFontCollection *collection, const WCHAR *name, DWRITE_FONT_WEIGHT weight, DWRITE_FONT_STYLE style, DWRITE_FONT_STRETCH stretch, REFIID riid, void **obj)
Definition: analyzer.c:2479
static struct fallback_data system_fallback
Definition: analyzer.c:554
IDWriteTextAnalyzer2 * get_text_analyzer(void)
Definition: analyzer.c:2241
BOOL lb_is_newline_char(WCHAR ch)
Definition: analyzer.c:851
const char * debugstr_sa_script(UINT16 script)
Definition: analyzer.c:209
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define index(s, c)
Definition: various.h:29
static void list_remove(struct list_entry *entry)
Definition: list.h:90
static void list_add_tail(struct list_entry *head, struct list_entry *entry)
Definition: list.h:83
static void list_add_head(struct list_entry *head, struct list_entry *entry)
Definition: list.h:76
static void list_init(struct list_entry *head)
Definition: list.h:51
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
const GUID IID_IUnknown
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
Definition: list.h:39
Definition: _locale.h:75
locale() _STLP_NOTHROW
Definition: locale.cpp:118
RECT rect
Definition: combotst.c:67
range
Definition: d3dx9_private.h:58
DWRITE_MEASURING_MODE
Definition: dcommon.idl:36
@ DWRITE_MEASURING_MODE_GDI_CLASSIC
Definition: dcommon.idl:38
@ DWRITE_MEASURING_MODE_NATURAL
Definition: dcommon.idl:37
@ DWRITE_MEASURING_MODE_GDI_NATURAL
Definition: dcommon.idl:39
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_NOTIMPL
Definition: ddrawi.h:99
#define E_FAIL
Definition: ddrawi.h:102
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
HRESULT hr
Definition: delayimp.cpp:582
static DWRITE_WORD_WRAPPING WINAPI dwritetextformat_layout_GetWordWrapping(IDWriteTextFormat3 *iface)
Definition: layout.c:4556
static HRESULT layout_resolve_fonts(struct dwrite_textlayout *layout)
Definition: layout.c:768
static HRESULT WINAPI dwritetextlayout_GetClusterMetrics(IDWriteTextLayout4 *iface, DWRITE_CLUSTER_METRICS *metrics, UINT32 max_count, UINT32 *count)
Definition: layout.c:3891
static HRESULT WINAPI dwritetextlayout_SetUnderline(IDWriteTextLayout4 *iface, BOOL underline, DWRITE_TEXT_RANGE range)
Definition: layout.c:3251
static void layout_shape_clear_user_features_context(struct shaping_context *context)
Definition: layout.c:839
static void free_layout_runs(struct dwrite_textlayout *layout)
Definition: layout.c:333
static ULONG WINAPI dwritetextlayout_source_AddRef(IDWriteTextAnalysisSource1 *iface)
Definition: layout.c:5048
static ULONG WINAPI dwritetypography_Release(IDWriteTypography *iface)
Definition: layout.c:5396
static DWRITE_TEXT_ALIGNMENT WINAPI dwritetextformat_layout_GetTextAlignment(IDWriteTextFormat3 *iface)
Definition: layout.c:4538
static HRESULT WINAPI dwritetextlayout2_SetFontFallback(IDWriteTextLayout4 *iface, IDWriteFontFallback *fallback)
Definition: layout.c:4137
static UINT32 WINAPI dwritetextformat3_layout_GetFontAxisValueCount(IDWriteTextFormat3 *iface)
Definition: layout.c:4809
static DWRITE_READING_DIRECTION WINAPI dwritetextformat_layout_GetReadingDirection(IDWriteTextFormat3 *iface)
Definition: layout.c:4565
static HRESULT get_string_attribute_value(const struct dwrite_textlayout *layout, enum layout_range_attr_kind kind, UINT32 position, WCHAR *ret, UINT32 length, DWRITE_TEXT_RANGE *r)
Definition: layout.c:2870
static HRESULT WINAPI dwritetextformat_layout_GetFontCollection(IDWriteTextFormat3 *iface, IDWriteFontCollection **collection)
Definition: layout.c:4619
static HRESULT set_layout_range_attr(struct dwrite_textlayout *layout, enum layout_range_attr_kind attr, struct layout_range_attr_value *value)
Definition: layout.c:2669
static float layout_get_line_width(const struct dwrite_textlayout *layout, const struct layout_effective_run *erun, const struct layout_effective_inline *inrun, UINT32 line)
Definition: layout.c:1553
static HRESULT WINAPI dwritetextlayout_layout_GetFontStyle(IDWriteTextLayout4 *iface, UINT32 position, DWRITE_FONT_STYLE *style, DWRITE_TEXT_RANGE *r)
Definition: layout.c:3399
static HRESULT WINAPI dwritetextformat_layout_SetReadingDirection(IDWriteTextFormat3 *iface, DWRITE_READING_DIRECTION direction)
Definition: layout.c:4455
static void free_layout_ranges_list(struct dwrite_textlayout *layout)
Definition: layout.c:2508
static BOOL is_same_u_splitting(const struct layout_underline_splitting_params *left, const struct layout_underline_splitting_params *right)
Definition: layout.c:1792
static HRESULT layout_shape_add_empty_user_features_range(struct shaping_context *context, unsigned int length)
Definition: layout.c:859
static BOOL WINAPI dwritetextlayout2_GetLastLineWrapping(IDWriteTextLayout4 *iface)
Definition: layout.c:4109
static BOOL d2d_rect_is_empty(const D2D1_RECT_F *rect)
Definition: layout.c:3731
static HRESULT WINAPI dwritetextlayout_layout_GetFontCollection(IDWriteTextLayout4 *iface, UINT32 position, IDWriteFontCollection **collection, DWRITE_TEXT_RANGE *r)
Definition: layout.c:3349
static struct layout_range_header * alloc_layout_range_from(struct layout_range_header *h, const DWRITE_TEXT_RANGE *r)
Definition: layout.c:2406
static HRESULT WINAPI dwritetextlayout3_SetLineSpacing(IDWriteTextLayout4 *iface, DWRITE_LINE_SPACING const *spacing)
Definition: layout.c:4165
static HRESULT WINAPI dwritetextlayout3_GetLineMetrics(IDWriteTextLayout4 *iface, DWRITE_LINE_METRICS1 *metrics, UINT32 max_count, UINT32 *count)
Definition: layout.c:4205
static FLOAT WINAPI dwritetextlayout_GetMaxHeight(IDWriteTextLayout4 *iface)
Definition: layout.c:3340
static void d2d_rect_union(D2D1_RECT_F *dst, const D2D1_RECT_F *src)
Definition: layout.c:3736
static DWRITE_READING_DIRECTION WINAPI dwritetextlayout_source_GetParagraphReadingDirection(IDWriteTextAnalysisSource1 *iface)
Definition: layout.c:5102
static HRESULT WINAPI dwritetextformat_layout_GetLineSpacing(IDWriteTextFormat3 *iface, DWRITE_LINE_SPACING_METHOD *method, FLOAT *spacing, FLOAT *baseline)
Definition: layout.c:4606
static HRESULT layout_set_vertical_orientation(struct dwrite_textlayout *layout, DWRITE_VERTICAL_GLYPH_ORIENTATION orientation)
Definition: layout.c:4066
static const IDWriteTextAnalysisSource1Vtbl dwritetextlayoutsourcevtbl
Definition: layout.c:5157
static DWRITE_FLOW_DIRECTION WINAPI dwritetextformat_layout_GetFlowDirection(IDWriteTextFormat3 *iface)
Definition: layout.c:4574
static struct dwrite_textlayout * impl_from_IDWriteTextAnalysisSource1(IDWriteTextAnalysisSource1 *iface)
Definition: layout.c:296
static void layout_splitting_params_from_pos(const struct dwrite_textlayout *layout, UINT32 pos, struct layout_final_splitting_params *params)
Definition: layout.c:1321
static void layout_set_cluster_metrics(struct dwrite_textlayout *layout, const struct layout_run *r, UINT32 *cluster)
Definition: layout.c:549
static HRESULT WINAPI dwritetextlayout_sink_SetLineBreakpoints(IDWriteTextAnalysisSink1 *iface, UINT32 position, UINT32 length, DWRITE_LINE_BREAKPOINT const *breakpoints)
Definition: layout.c:4938
static DWRITE_AUTOMATIC_FONT_AXES WINAPI dwritetextformat3_layout_GetAutomaticFontAxes(IDWriteTextFormat3 *iface)
Definition: layout.c:4828
static HRESULT layout_compute_effective_runs(struct dwrite_textlayout *layout)
Definition: layout.c:2132
static ULONG WINAPI dwritetextformat_layout_Release(IDWriteTextFormat3 *iface)
Definition: layout.c:4383
static float get_cluster_range_width(const struct dwrite_textlayout *layout, UINT32 start, UINT32 end)
Definition: layout.c:1285
static HRESULT WINAPI dwritetextlayout1_SetPairKerning(IDWriteTextLayout4 *iface, BOOL is_pairkerning_enabled, DWRITE_TEXT_RANGE range)
Definition: layout.c:3992
static HRESULT WINAPI dwritetextformat2_layout_GetLineSpacing(IDWriteTextFormat3 *iface, DWRITE_LINE_SPACING *spacing)
Definition: layout.c:4793
static HRESULT layout_compute_runs(struct dwrite_textlayout *layout)
Definition: layout.c:1150
static HRESULT WINAPI dwritetextlayout_GetUnderline(IDWriteTextLayout4 *iface, UINT32 position, BOOL *underline, DWRITE_TEXT_RANGE *r)
Definition: layout.c:3438
static HRESULT WINAPI dwritetextlayout4_SetFontAxisValues(IDWriteTextLayout4 *iface, DWRITE_FONT_AXIS_VALUE const *axis_values, UINT32 num_values, DWRITE_TEXT_RANGE range)
Definition: layout.c:4229
static HRESULT WINAPI dwritetextlayout_HitTestTextPosition(IDWriteTextLayout4 *iface, UINT32 textPosition, BOOL is_trailinghit, FLOAT *pointX, FLOAT *pointY, DWRITE_HIT_TEST_METRICS *metrics)
Definition: layout.c:3974
static HRESULT WINAPI dwritetextlayout_SetWordWrapping(IDWriteTextLayout4 *iface, DWRITE_WORD_WRAPPING wrapping)
Definition: layout.c:2978
static BOOL is_same_splitting_params(const struct layout_final_splitting_params *left, const struct layout_final_splitting_params *right)
Definition: layout.c:1329
static BOOL WINAPI dwritetextformat1_layout_GetLastLineWrapping(IDWriteTextFormat3 *iface)
Definition: layout.c:4738
static BOOL is_run_rtl(const struct layout_effective_run *run)
Definition: layout.c:316
static struct layout_effective_run * layout_get_prev_erun(const struct dwrite_textlayout *layout, const struct layout_effective_run *cur)
Definition: layout.c:1525
static ULONG WINAPI dwritetextlayout_sink_AddRef(IDWriteTextAnalysisSink1 *iface)
Definition: layout.c:4906
static DWRITE_FONT_WEIGHT WINAPI dwritetextlayout_GetFontWeight(IDWriteTextLayout4 *iface)
Definition: layout.c:3087
static HRESULT WINAPI dwritetextlayout_SetLocaleName(IDWriteTextLayout4 *iface, WCHAR const *locale, DWRITE_TEXT_RANGE range)
Definition: layout.c:3315
static HRESULT WINAPI dwritetextlayout_SetStrikethrough(IDWriteTextLayout4 *iface, BOOL strikethrough, DWRITE_TEXT_RANGE range)
Definition: layout.c:3263
static struct layout_range_spacing * layout_get_next_spacing_range(const struct dwrite_textlayout *layout, const struct layout_range_spacing *cur)
Definition: layout.c:1008
static HRESULT WINAPI dwritetextformat_layout_GetFontFamilyName(IDWriteTextFormat3 *iface, WCHAR *name, UINT32 size)
Definition: layout.c:4641
static HRESULT WINAPI dwritetextlayout_source_GetTextAtPosition(IDWriteTextAnalysisSource1 *iface, UINT32 position, WCHAR const **text, UINT32 *text_len)
Definition: layout.c:5060
static DWRITE_LINE_BREAKPOINT get_effective_breakpoint(const struct dwrite_textlayout *layout, UINT32 pos)
Definition: layout.c:493
static HRESULT layout_set_dummy_line_metrics(struct dwrite_textlayout *layout)
Definition: layout.c:1891
static BOOL is_same_text_range(const DWRITE_TEXT_RANGE *left, const DWRITE_TEXT_RANGE *right)
Definition: layout.c:2324
static HRESULT WINAPI dwritetextlayout_layout_GetLocaleNameLength(IDWriteTextLayout4 *iface, UINT32 position, UINT32 *length, DWRITE_TEXT_RANGE *r)
Definition: layout.c:3514
static HRESULT layout_shape_get_glyphs(struct dwrite_textlayout *layout, struct shaping_context *context)
Definition: layout.c:947
static HRESULT WINAPI dwritetextformat1_layout_SetFontFallback(IDWriteTextFormat3 *iface, IDWriteFontFallback *fallback)
Definition: layout.c:4766
static HRESULT WINAPI dwritetextformat_layout_SetWordWrapping(IDWriteTextFormat3 *iface, DWRITE_WORD_WRAPPING wrapping)
Definition: layout.c:4437
static HRESULT layout_add_underline(struct dwrite_textlayout *layout, struct layout_effective_run *first, struct layout_effective_run *last)
Definition: layout.c:1798
static BOOL layout_get_strikethrough_from_pos(const struct dwrite_textlayout *layout, UINT32 pos)
Definition: layout.c:1309
static ULONG WINAPI dwritetextlayout_sink_Release(IDWriteTextAnalysisSink1 *iface)
Definition: layout.c:4912
static UINT32 WINAPI dwritetextformat_layout_GetFontFamilyNameLength(IDWriteTextFormat3 *iface)
Definition: layout.c:4632
static HRESULT WINAPI dwritetextlayout_SetFontFamilyName(IDWriteTextLayout4 *iface, WCHAR const *name, DWRITE_TEXT_RANGE range)
Definition: layout.c:3172
static HRESULT WINAPI dwritetextlayout_SetDrawingEffect(IDWriteTextLayout4 *iface, IUnknown *effect, DWRITE_TEXT_RANGE range)
Definition: layout.c:3276
#define SCALE_FONT_METRIC(metric, emSize, metrics)
Definition: layout.c:585
static HRESULT WINAPI dwritetextlayout_SetTextAlignment(IDWriteTextLayout4 *iface, DWRITE_TEXT_ALIGNMENT alignment)
Definition: layout.c:2965
static UINT32 WINAPI dwritetextlayout4_GetFontAxisValueCount(IDWriteTextLayout4 *iface, UINT32 pos)
Definition: layout.c:4237
static void layout_add_line(struct dwrite_textlayout *layout, UINT32 first_cluster, UINT32 last_cluster, UINT32 *textpos)
Definition: layout.c:1926
static DWRITE_FONT_WEIGHT WINAPI dwritetextformat_layout_GetFontWeight(IDWriteTextFormat3 *iface)
Definition: layout.c:4652
static DWRITE_OPTICAL_ALIGNMENT WINAPI dwritetextformat1_layout_GetOpticalAlignment(IDWriteTextFormat3 *iface)
Definition: layout.c:4757
static DWRITE_TEXT_ALIGNMENT WINAPI dwritetextlayout_GetTextAlignment(IDWriteTextLayout4 *iface)
Definition: layout.c:3018
static HRESULT WINAPI dwritetextlayout3_InvalidateLayout(IDWriteTextLayout4 *iface)
Definition: layout.c:4155
layout_run_kind
Definition: layout.c:119
@ LAYOUT_RUN_INLINE
Definition: layout.c:121
@ LAYOUT_RUN_REGULAR
Definition: layout.c:120
static HRESULT WINAPI dwritetextlayout2_SetOpticalAlignment(IDWriteTextLayout4 *iface, DWRITE_OPTICAL_ALIGNMENT alignment)
Definition: layout.c:4118
static void layout_get_font_height(float emsize, const DWRITE_FONT_METRICS *fontmetrics, float *baseline, float *height)
Definition: layout.c:599
static struct dwrite_textlayout * impl_from_IDWriteTextFormat3(IDWriteTextFormat3 *iface)
Definition: layout.c:286
static HRESULT layout_format_from_textformat(struct dwrite_textlayout *layout, IDWriteTextFormat *format)
Definition: layout.c:5169
static HRESULT WINAPI dwritetextformat1_layout_GetFontFallback(IDWriteTextFormat3 *iface, IDWriteFontFallback **fallback)
Definition: layout.c:4776
static UINT32 WINAPI dwritetypography_GetFontFeatureCount(IDWriteTypography *iface)
Definition: layout.c:5429
static HRESULT WINAPI dwritetextlayout_GetTrimming(IDWriteTextLayout4 *iface, DWRITE_TRIMMING *options, IDWriteInlineObject **trimming_sign)
Definition: layout.c:3054
static void layout_initialize_text_source(struct dwrite_textlayout *layout, unsigned int offset, unsigned int length)
Definition: layout.c:605
static float layout_get_centered_shift(const struct dwrite_textlayout *layout, BOOL skiptransform, FLOAT width, FLOAT det)
Definition: layout.c:1665
static HRESULT WINAPI dwritetextlayout_DetermineMinWidth(IDWriteTextLayout4 *iface, FLOAT *min_width)
Definition: layout.c:3910
static struct layout_range_header * alloc_layout_range(struct dwrite_textlayout *layout, const DWRITE_TEXT_RANGE *r, enum layout_range_kind kind)
Definition: layout.c:2330
static FLOAT WINAPI dwritetextformat_layout_GetIncrementalTabStop(IDWriteTextFormat3 *iface)
Definition: layout.c:4583
static HRESULT WINAPI dwritetextlayout_SetFontSize(IDWriteTextLayout4 *iface, FLOAT size, DWRITE_TEXT_RANGE range)
Definition: layout.c:3236
static FLOAT renderer_apply_snapping(FLOAT coord, BOOL skiptransform, FLOAT ppdip, FLOAT det, const DWRITE_MATRIX *m)
Definition: layout.c:3534
static DWRITE_FLOW_DIRECTION WINAPI dwritetextlayout_GetFlowDirection(IDWriteTextLayout4 *iface)
Definition: layout.c:3042
static HRESULT WINAPI dwritetextlayout_SetReadingDirection(IDWriteTextLayout4 *iface, DWRITE_READING_DIRECTION direction)
Definition: layout.c:2984
static const IDWriteTypographyVtbl dwritetypographyvtbl
Definition: layout.c:5452
layout_range_kind
Definition: layout.c:74
@ LAYOUT_RANGE_REGULAR
Definition: layout.c:75
@ LAYOUT_RANGE_SPACING
Definition: layout.c:79
@ LAYOUT_RANGE_TYPOGRAPHY
Definition: layout.c:80
@ LAYOUT_RANGE_STRIKETHROUGH
Definition: layout.c:77
@ LAYOUT_RANGE_UNDERLINE
Definition: layout.c:76
@ LAYOUT_RANGE_EFFECT
Definition: layout.c:78
static void layout_apply_text_alignment(struct dwrite_textlayout *layout)
Definition: layout.c:1712
static void d2d_rect_offset(D2D1_RECT_F *rect, FLOAT x, FLOAT y)
Definition: layout.c:3723
static HRESULT WINAPI dwritetextlayout_layout_GetFontSize(IDWriteTextLayout4 *iface, UINT32 position, FLOAT *size, DWRITE_TEXT_RANGE *r)
Definition: layout.c:3425
static HRESULT WINAPI dwritetextlayout_GetOverhangMetrics(IDWriteTextLayout4 *iface, DWRITE_OVERHANG_METRICS *overhangs)
Definition: layout.c:3840
static BOOL is_same_layout_attributes(struct layout_range_header const *hleft, struct layout_range_header const *hright)
Definition: layout.c:2278
static HRESULT WINAPI dwritetextformat1_layout_SetOpticalAlignment(IDWriteTextFormat3 *iface, DWRITE_OPTICAL_ALIGNMENT alignment)
Definition: layout.c:4747
static HRESULT WINAPI dwritetextlayout_GetStrikethrough(IDWriteTextLayout4 *iface, UINT32 position, BOOL *strikethrough, DWRITE_TEXT_RANGE *r)
Definition: layout.c:3452
static HRESULT WINAPI dwritetextlayout_GetTypography(IDWriteTextLayout4 *iface, UINT32 position, IDWriteTypography **typography, DWRITE_TEXT_RANGE *r)
Definition: layout.c:3498
static BOOL is_same_layout_attrvalue(struct layout_range_header const *h, enum layout_range_attr_kind attr, struct layout_range_attr_value *value)
Definition: layout.c:2232
static void free_layout_eruns(struct dwrite_textlayout *layout)
Definition: layout.c:352
static HRESULT layout_shape_get_positions(struct dwrite_textlayout *layout, struct shaping_context *context)
Definition: layout.c:1085
static HRESULT WINAPI dwritetextlayout_GetLineMetrics(IDWriteTextLayout4 *iface, DWRITE_LINE_METRICS *metrics, UINT32 max_count, UINT32 *count)
Definition: layout.c:3680
HRESULT create_typography(IDWriteTypography **ret)
Definition: layout.c:5461
static HRESULT WINAPI dwritetextlayout_source_GetLocaleName(IDWriteTextAnalysisSource1 *iface, UINT32 position, UINT32 *text_len, WCHAR const **locale)
Definition: layout.c:5108
static HRESULT WINAPI dwritetextlayout_source_GetTextBeforePosition(IDWriteTextAnalysisSource1 *iface, UINT32 position, WCHAR const **text, UINT32 *text_len)
Definition: layout.c:5081
static HRESULT WINAPI dwritetextlayout_GetFontCollection(IDWriteTextLayout4 *iface, IDWriteFontCollection **collection)
Definition: layout.c:3069
static void layout_get_erun_font_metrics(const struct dwrite_textlayout *layout, const struct layout_effective_run *erun, DWRITE_FONT_METRICS *metrics)
Definition: layout.c:1337
static HRESULT WINAPI dwritetextlayout_HitTestTextRange(IDWriteTextLayout4 *iface, UINT32 textPosition, UINT32 textLength, FLOAT originX, FLOAT originY, DWRITE_HIT_TEST_METRICS *metrics, UINT32 max_metricscount, UINT32 *actual_metricscount)
Definition: layout.c:3982
static ULONG WINAPI dwritetypography_AddRef(IDWriteTypography *iface)
Definition: layout.c:5386
static HRESULT WINAPI dwritetextlayout_sink_SetScriptAnalysis(IDWriteTextAnalysisSink1 *iface, UINT32 position, UINT32 length, DWRITE_SCRIPT_ANALYSIS const *sa)
Definition: layout.c:4918
static HRESULT WINAPI dwritetextlayout_SetMaxWidth(IDWriteTextLayout4 *iface, FLOAT maxWidth)
Definition: layout.c:3123
static void init_cluster_metrics(const struct dwrite_textlayout *layout, const struct regular_layout_run *run, UINT16 start_glyph, UINT16 stop_glyph, UINT32 stop_position, UINT16 length, DWRITE_CLUSTER_METRICS *metrics)
Definition: layout.c:500
static struct dwrite_textlayout * impl_from_IDWriteTextLayout4(IDWriteTextLayout4 *iface)
Definition: layout.c:281
static void free_layout_range(struct layout_range_header *h)
Definition: layout.c:2475
static HRESULT WINAPI dwritetextlayout_GetFontFamilyName(IDWriteTextLayout4 *iface, WCHAR *name, UINT32 size)
Definition: layout.c:3081
static void layout_set_line_positions(struct dwrite_textlayout *layout)
Definition: layout.c:2087
static const IDWriteTextAnalysisSink1Vtbl dwritetextlayoutsinkvtbl
Definition: layout.c:5019
static HRESULT WINAPI dwritetextlayout_sink_SetNumberSubstitution(IDWriteTextAnalysisSink1 *iface, UINT32 position, UINT32 length, IDWriteNumberSubstitution *substitution)
Definition: layout.c:5006
static ULONG WINAPI dwritetextlayout_Release(IDWriteTextLayout4 *iface)
Definition: layout.c:2937
layout_range_attr_kind
Definition: layout.c:33
@ LAYOUT_RANGE_ATTR_INLINE
Definition: layout.c:39
@ LAYOUT_RANGE_ATTR_FONTFAMILY
Definition: layout.c:45
@ LAYOUT_RANGE_ATTR_LOCALE
Definition: layout.c:44
@ LAYOUT_RANGE_ATTR_STRETCH
Definition: layout.c:36
@ LAYOUT_RANGE_ATTR_WEIGHT
Definition: layout.c:34
@ LAYOUT_RANGE_ATTR_TYPOGRAPHY
Definition: layout.c:47
@ LAYOUT_RANGE_ATTR_UNDERLINE
Definition: layout.c:40
@ LAYOUT_RANGE_ATTR_STYLE
Definition: layout.c:35
@ LAYOUT_RANGE_ATTR_STRIKETHROUGH
Definition: layout.c:41
@ LAYOUT_RANGE_ATTR_EFFECT
Definition: layout.c:38
@ LAYOUT_RANGE_ATTR_FONTCOLL
Definition: layout.c:43
@ LAYOUT_RANGE_ATTR_PAIR_KERNING
Definition: layout.c:42
@ LAYOUT_RANGE_ATTR_FONTSIZE
Definition: layout.c:37
@ LAYOUT_RANGE_ATTR_SPACING
Definition: layout.c:46
static BOOL is_layout_gdi_compatible(const struct dwrite_textlayout *layout)
Definition: layout.c:311
static HRESULT WINAPI dwritetextlayout_layout_GetFontWeight(IDWriteTextLayout4 *iface, UINT32 position, DWRITE_FONT_WEIGHT *weight, DWRITE_TEXT_RANGE *r)
Definition: layout.c:3385
static HRESULT layout_add_effective_run(struct dwrite_textlayout *layout, const struct layout_run *r, UINT32 first_cluster, UINT32 cluster_count, UINT32 line, FLOAT origin_x, struct layout_final_splitting_params *params)
Definition: layout.c:1357
static DWRITE_FONT_STYLE WINAPI dwritetextformat_layout_GetFontStyle(IDWriteTextFormat3 *iface)
Definition: layout.c:4661
static DWRITE_OPTICAL_ALIGNMENT WINAPI dwritetextlayout2_GetOpticalAlignment(IDWriteTextLayout4 *iface)
Definition: layout.c:4128
static HRESULT WINAPI dwritetextlayout2_GetMetrics(IDWriteTextLayout4 *iface, DWRITE_TEXT_METRICS1 *metrics)
Definition: layout.c:4053
static HRESULT WINAPI dwritetextlayout_GetInlineObject(IDWriteTextLayout4 *iface, UINT32 position, IDWriteInlineObject **object, DWRITE_TEXT_RANGE *r)
Definition: layout.c:3482
static DWRITE_VERTICAL_GLYPH_ORIENTATION WINAPI dwritetextlayout2_GetVerticalGlyphOrientation(IDWriteTextLayout4 *iface)
Definition: layout.c:4091
static HRESULT WINAPI dwritetextlayout_source_GetNumberSubstitution(IDWriteTextAnalysisSource1 *iface, UINT32 position, UINT32 *text_len, IDWriteNumberSubstitution **substitution)
Definition: layout.c:5143
static UINT32 WINAPI dwritetextformat_layout_GetLocaleNameLength(IDWriteTextFormat3 *iface)
Definition: layout.c:4688
static BOOL layout_can_wrap_after(const struct dwrite_textlayout *layout, UINT32 cluster)
Definition: layout.c:2124
static HRESULT WINAPI dwritetextlayout1_SetCharacterSpacing(IDWriteTextLayout4 *iface, FLOAT leading, FLOAT trailing, FLOAT min_advance, DWRITE_TEXT_RANGE range)
Definition: layout.c:4019
static void init_u_splitting_params_from_erun(const struct layout_effective_run *erun, struct layout_underline_splitting_params *params)
Definition: layout.c:1785
static HRESULT WINAPI dwritetextlayout_SetFontWeight(IDWriteTextLayout4 *iface, DWRITE_FONT_WEIGHT weight, DWRITE_TEXT_RANGE range)
Definition: layout.c:3188
static HRESULT layout_update_metrics(struct dwrite_textlayout *layout)
Definition: layout.c:3704
static HRESULT return_range(const struct layout_range_header *h, DWRITE_TEXT_RANGE *r)
Definition: layout.c:2662
static const WCHAR * get_string_attribute_ptr(const struct layout_range *range, enum layout_range_attr_kind kind)
Definition: layout.c:2835
static HRESULT get_string_attribute_length(const struct dwrite_textlayout *layout, enum layout_range_attr_kind kind, UINT32 position, UINT32 *length, DWRITE_TEXT_RANGE *r)
Definition: layout.c:2853
layout_recompute_mask
Definition: layout.c:207
@ RECOMPUTE_LINES
Definition: layout.c:210
@ RECOMPUTE_EVERYTHING
Definition: layout.c:213
@ RECOMPUTE_MINIMAL_WIDTH
Definition: layout.c:209
@ RECOMPUTE_LINES_AND_OVERHANGS
Definition: layout.c:212
@ RECOMPUTE_CLUSTERS
Definition: layout.c:208
@ RECOMPUTE_OVERHANGS
Definition: layout.c:211
static void layout_apply_leading_alignment(struct dwrite_textlayout *layout)
Definition: layout.c:1612
static HRESULT layout_update_breakpoints_range(struct dwrite_textlayout *layout, const struct layout_range *cur)
Definition: layout.c:414
static DWRITE_FONT_STRETCH WINAPI dwritetextlayout_GetFontStretch(IDWriteTextLayout4 *iface)
Definition: layout.c:3099
static HRESULT WINAPI dwritetextformat3_layout_GetFontAxisValues(IDWriteTextFormat3 *iface, DWRITE_FONT_AXIS_VALUE *axis_values, UINT32 num_values)
Definition: layout.c:4818
static HRESULT WINAPI dwritetextlayout_SetFontCollection(IDWriteTextLayout4 *iface, IDWriteFontCollection *collection, DWRITE_TEXT_RANGE range)
Definition: layout.c:3159
static void layout_get_erun_bbox(struct dwrite_textlayout *layout, struct layout_effective_run *run, D2D1_RECT_F *bbox)
Definition: layout.c:3756
static DWRITE_READING_DIRECTION WINAPI dwritetextlayout_GetReadingDirection(IDWriteTextLayout4 *iface)
Definition: layout.c:3036
static FLOAT WINAPI dwritetextformat_layout_GetFontSize(IDWriteTextFormat3 *iface)
Definition: layout.c:4679
static ULONG WINAPI dwritetextlayout_source_Release(IDWriteTextAnalysisSource1 *iface)
Definition: layout.c:5054
static HRESULT WINAPI dwritetextlayout_source_GetVerticalGlyphOrientation(IDWriteTextAnalysisSource1 *iface, UINT32 position, UINT32 *length, DWRITE_VERTICAL_GLYPH_ORIENTATION *orientation, UINT8 *bidi_level)
Definition: layout.c:5150
static void layout_shape_clear_context(struct shaping_context *context)
Definition: layout.c:852
static HRESULT layout_run_get_last_resort_font(const struct dwrite_textlayout *layout, const struct layout_range *range, IDWriteFontFace **fontface, float *size)
Definition: layout.c:738
static FLOAT WINAPI dwritetextlayout_GetFontSize(IDWriteTextLayout4 *iface)
Definition: layout.c:3105
static HRESULT WINAPI dwritetextlayout2_GetFontFallback(IDWriteTextLayout4 *iface, IDWriteFontFallback **fallback)
Definition: layout.c:4146
static HRESULT WINAPI dwritetextlayout_sink_SetBidiLevel(IDWriteTextAnalysisSink1 *iface, UINT32 position, UINT32 length, UINT8 explicitLevel, UINT8 resolvedLevel)
Definition: layout.c:4950
static void layout_apply_snapping(D2D1_POINT_2F *vec, BOOL skiptransform, FLOAT ppdip, const DWRITE_MATRIX *m, FLOAT det)
Definition: layout.c:1582
static HRESULT WINAPI dwritetextformat1_layout_SetLastLineWrapping(IDWriteTextFormat3 *iface, BOOL lastline_wrapping_enabled)
Definition: layout.c:4727
static HRESULT WINAPI dwritetextlayout_GetDrawingEffect(IDWriteTextLayout4 *iface, UINT32 position, IUnknown **effect, DWRITE_TEXT_RANGE *r)
Definition: layout.c:3466
static HRESULT WINAPI dwritetextlayout_QueryInterface(IDWriteTextLayout4 *iface, REFIID riid, void **obj)
Definition: layout.c:2892
static UINT32 get_clipped_range_length(const struct dwrite_textlayout *layout, const struct layout_range *range)
Definition: layout.c:406
static void layout_apply_par_alignment(struct dwrite_textlayout *layout)
Definition: layout.c:1733
static UINT32 WINAPI dwritetextlayout_GetFontFamilyNameLength(IDWriteTextLayout4 *iface)
Definition: layout.c:3075
static const IDWriteTextFormat3Vtbl dwritetextformat3_layout_vtbl
Definition: layout.c:4841
HRESULT create_textlayout(const struct textlayout_desc *desc, IDWriteTextLayout **layout)
Definition: layout.c:5346
static DWRITE_FONT_STRETCH WINAPI dwritetextformat_layout_GetFontStretch(IDWriteTextFormat3 *iface)
Definition: layout.c:4670
static BOOL set_layout_range_iface_attr(IUnknown **dest, IUnknown *value)
Definition: layout.c:2562
static DWRITE_FONT_STYLE WINAPI dwritetextlayout_GetFontStyle(IDWriteTextLayout4 *iface)
Definition: layout.c:3093
static HRESULT WINAPI dwritetextlayout_SetParagraphAlignment(IDWriteTextLayout4 *iface, DWRITE_PARAGRAPH_ALIGNMENT alignment)
Definition: layout.c:2971
static void layout_apply_line_spacing(struct dwrite_textlayout *layout, UINT32 line)
Definition: layout.c:1469
static HRESULT WINAPI dwritetextlayout_Draw(IDWriteTextLayout4 *iface, void *context, IDWriteTextRenderer *renderer, FLOAT origin_x, FLOAT origin_y)
Definition: layout.c:3561
static HRESULT WINAPI dwritetextlayout_SetFontStyle(IDWriteTextLayout4 *iface, DWRITE_FONT_STYLE style, DWRITE_TEXT_RANGE range)
Definition: layout.c:3204
static HRESULT WINAPI dwritetextlayout_HitTestPoint(IDWriteTextLayout4 *iface, FLOAT pointX, FLOAT pointY, BOOL *is_trailinghit, BOOL *is_inside, DWRITE_HIT_TEST_METRICS *metrics)
Definition: layout.c:3966
static BOOL set_layout_range_attrval(struct layout_range_header *h, enum layout_range_attr_kind attr, struct layout_range_attr_value *value)
Definition: layout.c:2575
static HRESULT WINAPI dwritetextformat_layout_SetTextAlignment(IDWriteTextFormat3 *iface, DWRITE_TEXT_ALIGNMENT alignment)
Definition: layout.c:4389
static BOOL layout_get_underline_from_pos(const struct dwrite_textlayout *layout, UINT32 pos)
Definition: layout.c:1315
static DWRITE_AUTOMATIC_FONT_AXES WINAPI dwritetextlayout4_GetAutomaticFontAxes(IDWriteTextLayout4 *iface)
Definition: layout.c:4252
static struct regular_layout_run * layout_get_last_run(const struct dwrite_textlayout *layout)
Definition: layout.c:1876
static HRESULT WINAPI dwritetextlayout_GetLocaleName(IDWriteTextLayout4 *iface, WCHAR *name, UINT32 size)
Definition: layout.c:3117
static IUnknown * layout_get_effect_from_pos(const struct dwrite_textlayout *layout, UINT32 pos)
Definition: layout.c:1293
static struct layout_effective_inline * layout_get_next_inline_run(const struct dwrite_textlayout *layout, const struct layout_effective_inline *cur)
Definition: layout.c:1539
static DWRITE_PARAGRAPH_ALIGNMENT WINAPI dwritetextlayout_GetParagraphAlignment(IDWriteTextLayout4 *iface)
Definition: layout.c:3024
static HRESULT layout_shape_run(struct dwrite_textlayout *layout, struct regular_layout_run *run)
Definition: layout.c:1126
static UINT32 WINAPI dwritetextlayout_GetLocaleNameLength(IDWriteTextLayout4 *iface)
Definition: layout.c:3111
static HRESULT WINAPI dwritetextformat_layout_GetTrimming(IDWriteTextFormat3 *iface, DWRITE_TRIMMING *options, IDWriteInlineObject **trimming_sign)
Definition: layout.c:4592
static HRESULT layout_itemize(struct dwrite_textlayout *layout)
Definition: layout.c:612
static HRESULT WINAPI dwritetextlayout_SetLineSpacing(IDWriteTextLayout4 *iface, DWRITE_LINE_SPACING_METHOD spacing, FLOAT line_spacing, FLOAT baseline)
Definition: layout.c:3010
static DWRITE_PARAGRAPH_ALIGNMENT WINAPI dwritetextformat_layout_GetParagraphAlignment(IDWriteTextFormat3 *iface)
Definition: layout.c:4547
static HRESULT WINAPI dwritetextlayout_SetTypography(IDWriteTextLayout4 *iface, IDWriteTypography *typography, DWRITE_TEXT_RANGE range)
Definition: layout.c:3302
static HRESULT WINAPI dwritetextlayout2_SetVerticalGlyphOrientation(IDWriteTextLayout4 *iface, DWRITE_VERTICAL_GLYPH_ORIENTATION orientation)
Definition: layout.c:4081
static DWRITE_VERTICAL_GLYPH_ORIENTATION WINAPI dwritetextformat1_layout_GetVerticalGlyphOrientation(IDWriteTextFormat3 *iface)
Definition: layout.c:4718
static HRESULT WINAPI dwritetextlayout1_GetCharacterSpacing(IDWriteTextLayout4 *iface, UINT32 position, FLOAT *leading, FLOAT *trailing, FLOAT *min_advance, DWRITE_TEXT_RANGE *r)
Definition: layout.c:4037
static HRESULT WINAPI dwritetextlayout2_SetLastLineWrapping(IDWriteTextLayout4 *iface, BOOL lastline_wrapping_enabled)
Definition: layout.c:4100
static HRESULT WINAPI dwritetextlayout_GetLineSpacing(IDWriteTextLayout4 *iface, DWRITE_LINE_SPACING_METHOD *method, FLOAT *spacing, FLOAT *baseline)
Definition: layout.c:3061
static HRESULT layout_shape_apply_character_spacing(struct dwrite_textlayout *layout, struct shaping_context *context)
Definition: layout.c:1015
static HRESULT WINAPI dwritetextlayout_layout_GetFontStretch(IDWriteTextLayout4 *iface, UINT32 position, DWRITE_FONT_STRETCH *stretch, DWRITE_TEXT_RANGE *r)
Definition: layout.c:3412
static HRESULT WINAPI dwritetextformat_layout_SetLineSpacing(IDWriteTextFormat3 *iface, DWRITE_LINE_SPACING_METHOD method, FLOAT height, FLOAT baseline)
Definition: layout.c:4523
static FLOAT WINAPI dwritetextlayout_GetMaxWidth(IDWriteTextLayout4 *iface)
Definition: layout.c:3331
#define SNAP_COORD(x)
static struct layout_range * get_layout_range_by_pos(const struct dwrite_textlayout *layout, UINT32 pos)
Definition: layout.c:465
static ULONG WINAPI dwritetextformat_layout_AddRef(IDWriteTextFormat3 *iface)
Definition: layout.c:4377
static const char * debugstr_rundescr(const DWRITE_GLYPH_RUN_DESCRIPTION *descr)
Definition: layout.c:306
static HRESULT layout_map_run_characters(struct dwrite_textlayout *layout, struct layout_run *r, IDWriteFontFallback *fallback, struct layout_run **remaining)
Definition: layout.c:660
static HRESULT WINAPI dwritetextlayout_SetFontStretch(IDWriteTextLayout4 *iface, DWRITE_FONT_STRETCH stretch, DWRITE_TEXT_RANGE range)
Definition: layout.c:3220
static HRESULT WINAPI dwritetextlayout_SetTrimming(IDWriteTextLayout4 *iface, DWRITE_TRIMMING const *trimming, IDWriteInlineObject *trimming_sign)
Definition: layout.c:3003
static HRESULT WINAPI dwritetextformat_layout_QueryInterface(IDWriteTextFormat3 *iface, REFIID riid, void **obj)
Definition: layout.c:4368
static HRESULT WINAPI dwritetypography_QueryInterface(IDWriteTypography *iface, REFIID riid, void **obj)
Definition: layout.c:5369
static HRESULT WINAPI dwritetextlayout3_GetLineSpacing(IDWriteTextLayout4 *iface, DWRITE_LINE_SPACING *spacing)
Definition: layout.c:4195
static HRESULT WINAPI dwritetextformat_layout_SetIncrementalTabStop(IDWriteTextFormat3 *iface, FLOAT tabstop)
Definition: layout.c:4493
static HRESULT WINAPI dwritetextlayout_GetMetrics(IDWriteTextLayout4 *iface, DWRITE_TEXT_METRICS *metrics)
Definition: layout.c:3709
static HRESULT WINAPI dwritetextlayout_sink_SetGlyphOrientation(IDWriteTextAnalysisSink1 *iface, UINT32 position, UINT32 length, DWRITE_GLYPH_ORIENTATION_ANGLE angle, UINT8 adjusted_bidi_level, BOOL is_sideways, BOOL is_rtl)
Definition: layout.c:5012
static void layout_apply_trailing_alignment(struct dwrite_textlayout *layout)
Definition: layout.c:1634
static DWRITE_BREAK_CONDITION override_break_condition(DWRITE_BREAK_CONDITION existingbreak, DWRITE_BREAK_CONDITION newbreak)
Definition: layout.c:386
static HRESULT WINAPI dwritetextlayout_SetFlowDirection(IDWriteTextLayout4 *iface, DWRITE_FLOW_DIRECTION direction)
Definition: layout.c:2991
static void layout_apply_centered_alignment(struct dwrite_textlayout *layout)
Definition: layout.c:1677
static HRESULT WINAPI dwritetextlayout_SetInlineObject(IDWriteTextLayout4 *iface, IDWriteInlineObject *object, DWRITE_TEXT_RANGE range)
Definition: layout.c:3289
static HRESULT WINAPI dwritetextformat1_layout_SetVerticalGlyphOrientation(IDWriteTextFormat3 *iface, DWRITE_VERTICAL_GLYPH_ORIENTATION orientation)
Definition: layout.c:4708
static ULONG WINAPI dwritetextlayout_AddRef(IDWriteTextLayout4 *iface)
Definition: layout.c:2927
static BOOL should_skip_transform(const DWRITE_MATRIX *m, FLOAT *det)
Definition: layout.c:1575
static const IDWriteTextLayout4Vtbl dwritetextlayoutvtbl
Definition: layout.c:4275
static HRESULT WINAPI dwritetextlayout_sink_QueryInterface(IDWriteTextAnalysisSink1 *iface, REFIID riid, void **obj)
Definition: layout.c:4888
static HRESULT WINAPI dwritetextformat_layout_GetLocaleName(IDWriteTextFormat3 *iface, WCHAR *name, UINT32 size)
Definition: layout.c:4697
static HRESULT init_textlayout(const struct textlayout_desc *desc, struct dwrite_textlayout *layout)
Definition: layout.c:5265
static HRESULT WINAPI dwritetextlayout_SetMaxHeight(IDWriteTextLayout4 *iface, FLOAT maxHeight)
Definition: layout.c:3141
static HRESULT WINAPI dwritetextlayout_layout_GetLocaleName(IDWriteTextLayout4 *iface, UINT32 position, WCHAR *locale, UINT32 length, DWRITE_TEXT_RANGE *r)
Definition: layout.c:3524
static HRESULT alloc_layout_run(enum layout_run_kind kind, unsigned int start_position, struct layout_run **run)
Definition: layout.c:321
static DWRITE_WORD_WRAPPING WINAPI dwritetextlayout_GetWordWrapping(IDWriteTextLayout4 *iface)
Definition: layout.c:3030
static HRESULT WINAPI dwritetextlayout4_GetFontAxisValues(IDWriteTextLayout4 *iface, UINT32 pos, DWRITE_FONT_AXIS_VALUE *values, UINT32 num_values, DWRITE_TEXT_RANGE *range)
Definition: layout.c:4244
static HRESULT WINAPI dwritetextlayout_source_QueryInterface(IDWriteTextAnalysisSource1 *iface, REFIID riid, void **obj)
Definition: layout.c:5030
static HRESULT WINAPI dwritetextformat_layout_SetTrimming(IDWriteTextFormat3 *iface, DWRITE_TRIMMING const *trimming, IDWriteInlineObject *trimming_sign)
Definition: layout.c:4506
static HRESULT layout_compute(struct dwrite_textlayout *layout)
Definition: layout.c:1240
static BOOL is_in_layout_range(const DWRITE_TEXT_RANGE *outer, const DWRITE_TEXT_RANGE *inner)
Definition: layout.c:2656
static HRESULT WINAPI dwritetextformat_layout_SetFlowDirection(IDWriteTextFormat3 *iface, DWRITE_FLOW_DIRECTION direction)
Definition: layout.c:4474
static struct dwrite_typography * impl_from_IDWriteTypography(IDWriteTypography *iface)
Definition: layout.c:301
static HRESULT WINAPI dwritetextformat2_layout_SetLineSpacing(IDWriteTextFormat3 *iface, DWRITE_LINE_SPACING const *spacing)
Definition: layout.c:4786
static HRESULT WINAPI dwritetextlayout_SetIncrementalTabStop(IDWriteTextLayout4 *iface, FLOAT tabstop)
Definition: layout.c:2997
static HRESULT WINAPI dwritetextlayout_layout_GetFontFamilyNameLength(IDWriteTextLayout4 *iface, UINT32 position, UINT32 *length, DWRITE_TEXT_RANGE *r)
Definition: layout.c:3365
static HRESULT WINAPI dwritetextformat3_layout_SetAutomaticFontAxes(IDWriteTextFormat3 *iface, DWRITE_AUTOMATIC_FONT_AXES axes)
Definition: layout.c:4834
static HRESULT WINAPI dwritetextformat_layout_SetParagraphAlignment(IDWriteTextFormat3 *iface, DWRITE_PARAGRAPH_ALIGNMENT alignment)
Definition: layout.c:4413
static HRESULT WINAPI dwritetextlayout_layout_GetFontFamilyName(IDWriteTextLayout4 *iface, UINT32 position, WCHAR *name, UINT32 length, DWRITE_TEXT_RANGE *r)
Definition: layout.c:3375
static HRESULT WINAPI dwritetypography_GetFontFeature(IDWriteTypography *iface, UINT32 index, DWRITE_FONT_FEATURE *feature)
Definition: layout.c:5438
static HRESULT WINAPI dwritetypography_AddFontFeature(IDWriteTypography *iface, DWRITE_FONT_FEATURE feature)
Definition: layout.c:5412
static HRESULT layout_shape_get_user_features(const struct dwrite_textlayout *layout, struct shaping_context *context)
Definition: layout.c:873
static FLOAT WINAPI dwritetextlayout_GetIncrementalTabStop(IDWriteTextLayout4 *iface)
Definition: layout.c:3048
static struct dwrite_textlayout * impl_from_IDWriteTextAnalysisSink1(IDWriteTextAnalysisSink1 *iface)
Definition: layout.c:291
static void layout_get_font_metrics(const struct dwrite_textlayout *layout, IDWriteFontFace *fontface, float emsize, DWRITE_FONT_METRICS *fontmetrics)
Definition: layout.c:587
static void layout_get_inlineobj_bbox(const struct layout_effective_inline *run, D2D1_RECT_F *bbox)
Definition: layout.c:3815
static HRESULT layout_set_line_metrics(struct dwrite_textlayout *layout, DWRITE_LINE_METRICS1 *metrics)
Definition: layout.c:1490
static struct layout_range_header * get_layout_range_header_by_pos(const struct list *ranges, UINT32 pos)
Definition: layout.c:479
static struct layout_range_header * find_outer_range(struct list *ranges, const DWRITE_TEXT_RANGE *range)
Definition: layout.c:2543
static struct layout_effective_run * layout_get_next_erun(const struct dwrite_textlayout *layout, const struct layout_effective_run *cur)
Definition: layout.c:1511
static HRESULT WINAPI dwritetextlayout1_GetPairKerning(IDWriteTextLayout4 *iface, UINT32 position, BOOL *is_pairkerning_enabled, DWRITE_TEXT_RANGE *r)
Definition: layout.c:4005
static HRESULT WINAPI dwritetextformat3_layout_SetFontAxisValues(IDWriteTextFormat3 *iface, DWRITE_FONT_AXIS_VALUE const *axis_values, UINT32 num_values)
Definition: layout.c:4799
static HRESULT WINAPI dwritetextlayout4_SetAutomaticFontAxes(IDWriteTextLayout4 *iface, DWRITE_AUTOMATIC_FONT_AXES axes)
Definition: layout.c:4261
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
const char * wine_dbg_sprintf(const char *format,...)
Definition: compat.c:296
#define TRACE_ON(x)
Definition: compat.h:75
#define wcsicmp
Definition: compat.h:15
const WCHAR * text
Definition: package.c:1826
unsigned char ch[4][2]
Definition: console.c:118
#define assert(_expr)
Definition: assert.h:32
_ACRTIMP size_t __cdecl wcslen(const wchar_t *)
Definition: wcs.c:2988
_ACRTIMP int __cdecl wcscmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:1977
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2807
_ACRTIMP float __cdecl fabsf(float)
static wchar_t * wcslwr(wchar_t *str)
Definition: string.h:96
static wchar_t * wcsdup(const wchar_t *str)
Definition: string.h:94
method
Definition: dragdrop.c:54
return ret
Definition: mutex.c:147
#define L(x)
Definition: resources.c:13
@ DWRITE_SCRIPT_SHAPES_NO_VISUAL
Definition: dwrite.idl:330
DWRITE_PARAGRAPH_ALIGNMENT
Definition: dwrite.idl:183
@ DWRITE_PARAGRAPH_ALIGNMENT_FAR
Definition: dwrite.idl:185
@ DWRITE_PARAGRAPH_ALIGNMENT_NEAR
Definition: dwrite.idl:184
@ DWRITE_PARAGRAPH_ALIGNMENT_CENTER
Definition: dwrite.idl:186
DWRITE_BREAK_CONDITION
Definition: dwrite.idl:222
@ DWRITE_BREAK_CONDITION_MUST_BREAK
Definition: dwrite.idl:226
@ DWRITE_BREAK_CONDITION_CAN_BREAK
Definition: dwrite.idl:224
@ DWRITE_BREAK_CONDITION_MAY_NOT_BREAK
Definition: dwrite.idl:225
@ DWRITE_BREAK_CONDITION_NEUTRAL
Definition: dwrite.idl:223
DWRITE_WORD_WRAPPING
Definition: dwrite.idl:190
@ DWRITE_WORD_WRAPPING_NO_WRAP
Definition: dwrite.idl:192
@ DWRITE_WORD_WRAPPING_CHARACTER
Definition: dwrite.idl:195
DWRITE_FONT_WEIGHT
Definition: dwrite.idl:73
@ DWRITE_FONT_WEIGHT_ULTRA_BLACK
Definition: dwrite.idl:90
DWRITE_FLOW_DIRECTION
Definition: dwrite.idl:207
DWRITE_FONT_STYLE
Definition: dwrite.idl:109
@ DWRITE_FONT_STYLE_ITALIC
Definition: dwrite.idl:112
DWRITE_TEXT_ALIGNMENT
Definition: dwrite.idl:175
@ DWRITE_TEXT_ALIGNMENT_CENTER
Definition: dwrite.idl:178
@ DWRITE_TEXT_ALIGNMENT_JUSTIFIED
Definition: dwrite.idl:179
@ DWRITE_TEXT_ALIGNMENT_LEADING
Definition: dwrite.idl:176
@ DWRITE_TEXT_ALIGNMENT_TRAILING
Definition: dwrite.idl:177
@ DWRITE_TRIMMING_GRANULARITY_CHARACTER
Definition: dwrite.idl:217
@ DWRITE_TRIMMING_GRANULARITY_NONE
Definition: dwrite.idl:216
DWRITE_READING_DIRECTION
Definition: dwrite.idl:199
@ DWRITE_READING_DIRECTION_RIGHT_TO_LEFT
Definition: dwrite.idl:201
@ DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
Definition: dwrite.idl:200
DWRITE_FONT_STRETCH
Definition: dwrite.idl:94
@ DWRITE_FONT_STRETCH_UNDEFINED
Definition: dwrite.idl:95
@ DWRITE_FONT_STRETCH_ULTRA_EXPANDED
Definition: dwrite.idl:105
DWRITE_LINE_SPACING_METHOD
Definition: dwrite.idl:230
@ DWRITE_LINE_SPACING_METHOD_PROPORTIONAL
Definition: dwrite.idl:233
@ DWRITE_LINE_SPACING_METHOD_UNIFORM
Definition: dwrite.idl:232
@ DWRITE_LINE_SPACING_METHOD_DEFAULT
Definition: dwrite.idl:231
DWRITE_GLYPH_ORIENTATION_ANGLE
Definition: dwrite_1.idl:432
DWRITE_VERTICAL_GLYPH_ORIENTATION
Definition: dwrite_1.idl:426
DWRITE_OPTICAL_ALIGNMENT
Definition: dwrite_2.idl:22
DWRITE_AUTOMATIC_FONT_AXES
Definition: dwrite_3.idl:156
@ DWRITE_AUTOMATIC_FONT_AXES_OPTICAL_SIZE
Definition: dwrite_3.idl:158
FLOAT baseline
Definition: dwrite_3.idl:860
DWRITE_LINE_METRICS1
Definition: dwrite_3.idl:864
HRESULT format_set_textalignment(struct dwrite_textformat_data *format, DWRITE_TEXT_ALIGNMENT alignment, BOOL *changed)
Definition: format.c:58
HRESULT format_set_trimming(struct dwrite_textformat_data *format, DWRITE_TRIMMING const *trimming, IDWriteInlineObject *trimming_sign, BOOL *changed)
Definition: format.c:104
HRESULT format_get_font_axisvalues(struct dwrite_textformat_data *format, DWRITE_FONT_AXIS_VALUE *axis_values, unsigned int num_values)
Definition: format.c:159
HRESULT format_set_wordwrapping(struct dwrite_textformat_data *format, DWRITE_WORD_WRAPPING wrapping, BOOL *changed)
Definition: format.c:86
HRESULT format_set_font_axisvalues(struct dwrite_textformat_data *format, DWRITE_FONT_AXIS_VALUE const *axis_values, unsigned int num_values)
Definition: format.c:141
static const char * debugstr_range(const DWRITE_TEXT_RANGE *range)
HRESULT format_set_fontfallback(struct dwrite_textformat_data *format, IDWriteFontFallback *fallback)
Definition: format.c:184
struct dwrite_textformat * unsafe_impl_from_IDWriteTextFormat(IDWriteTextFormat *iface)
Definition: format.c:708
HRESULT format_set_linespacing(struct dwrite_textformat_data *format, DWRITE_LINE_SPACING const *spacing, BOOL *changed)
Definition: format.c:128
HRESULT format_set_paralignment(struct dwrite_textformat_data *format, DWRITE_PARAGRAPH_ALIGNMENT alignment, BOOL *changed)
Definition: format.c:68
static LPWSTR heap_strdupnW(const WCHAR *str, UINT32 len)
HRESULT format_get_fontfallback(const struct dwrite_textformat_data *format, IDWriteFontFallback **fallback)
Definition: format.c:176
void release_format_data(struct dwrite_textformat_data *data)
Definition: format.c:40
HRESULT format_set_vertical_orientation(struct dwrite_textformat_data *format, DWRITE_VERTICAL_GLYPH_ORIENTATION orientation, BOOL *changed)
Definition: format.c:202
HRESULT format_set_flowdirection(struct dwrite_textformat_data *format, DWRITE_FLOW_DIRECTION direction, BOOL *changed)
Definition: format.c:95
HRESULT format_set_optical_alignment(struct dwrite_textformat_data *format, DWRITE_OPTICAL_ALIGNMENT alignment)
Definition: format.c:194
void dwrite_fontface_get_glyph_bbox(IDWriteFontFace *fontface, struct dwrite_glyphbitmap *bitmap)
Definition: font.c:158
HRESULT compute_glyph_origins(DWRITE_GLYPH_RUN const *run, DWRITE_MEASURING_MODE measuring_mode, D2D1_POINT_2F baseline_origin, DWRITE_MATRIX const *transform, D2D1_POINT_2F *origins)
Definition: main.c:1726
static BOOL dwrite_array_reserve(void **elements, size_t *capacity, size_t count, size_t size)
HRESULT format_set_readingdirection(struct dwrite_textformat_data *format, DWRITE_READING_DIRECTION direction, BOOL *changed)
Definition: format.c:77
unsigned int BOOL
Definition: ntddk_ex.h:94
FT_Vector * vec
Definition: ftbbox.c:469
FT_BBox bbox
Definition: ftbbox.c:467
Character const *const size_t const max_count
Definition: fullpath.cpp:66
FxCollectionEntry * cur
GLuint start
Definition: gl.h:1545
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
GLdouble s
Definition: gl.h:2039
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLuint GLuint end
Definition: gl.h:1545
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLint GLint GLsizei width
Definition: gl.h:1546
GLenum GLenum GLenum GLenum GLenum scale
Definition: glext.h:9032
GLenum src
Definition: glext.h:6340
GLsizeiptr size
Definition: glext.h:5919
GLintptr offset
Definition: glext.h:5920
GLuint coord
Definition: glext.h:9511
const GLubyte * c
Definition: glext.h:8905
GLuint index
Definition: glext.h:6031
GLdouble GLdouble right
Definition: glext.h:10859
GLsizei GLenum const GLvoid GLuint GLsizei GLfloat * metrics
Definition: glext.h:11745
GLfloat f
Definition: glext.h:7540
GLenum const GLfloat * params
Definition: glext.h:5645
GLuint in
Definition: glext.h:9616
GLint left
Definition: glext.h:7726
GLenum GLenum dst
Definition: glext.h:6340
GLboolean GLenum GLenum GLvoid * values
Definition: glext.h:5666
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
const GLint * first
Definition: glext.h:5794
GLfloat angle
Definition: glext.h:10853
GLdouble GLdouble u2
Definition: glext.h:8308
GLenum GLsizei len
Definition: glext.h:6722
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:6102
const GLfloat * m
Definition: glext.h:10848
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
REFIID riid
Definition: atlbase.h:39
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
uint32_t entry
Definition: isohybrid.c:63
#define e
Definition: ke_i.h:82
#define f
Definition: ke_i.h:83
#define debugstr_guid
Definition: kernel32.h:35
#define debugstr_w
Definition: kernel32.h:32
if(dx< 0)
Definition: linetemp.h:194
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
D3D11_SHADER_VARIABLE_DESC desc
Definition: reflection.c:1683
static const LARGE_INTEGER *static const HANDLE const LARGE_INTEGER *static PSLIST_ENTRY PSLIST_ENTRY last
Definition: sync.c:64
static char * dest
Definition: rtl.c:149
static IUnknown * outer
Definition: compobj.c:82
static BOOL is_rtl(void)
Definition: editor.c:53
INTERNETFEATURELIST feature
Definition: misc.c:1807
#define shift
Definition: input.c:3280
#define min(a, b)
Definition: monoChain.cc:55
#define floorf(x)
Definition: mymath.h:65
Definition: mk_font.cpp:20
direction
Definition: netio.c:882
#define LOCALE_NAME_MAX_LENGTH
short WCHAR
Definition: pedump.c:58
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
#define REFIID
Definition: guiddef.h:118
static unsigned __int64 next
Definition: rand_nt.c:6
#define calloc
Definition: rosglue.h:14
const WCHAR * str
wcscpy
static __inline const char * debugstr_fourcc(unsigned int cc)
Definition: debug.h:397
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:236
__WINE_SERVER_LIST_INLINE struct list * list_prev(const struct list *list, const struct list *elem)
Definition: list.h:125
#define LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, list, type, field)
Definition: list.h:242
__WINE_SERVER_LIST_INLINE struct list * list_next(const struct list *list, const struct list *elem)
Definition: list.h:117
__WINE_SERVER_LIST_INLINE void list_add_before(struct list *elem, struct list *to_add)
Definition: list.h:89
__WINE_SERVER_LIST_INLINE void list_add_after(struct list *elem, struct list *to_add)
Definition: list.h:80
__WINE_SERVER_LIST_INLINE struct list * list_tail(const struct list *list)
Definition: list.h:139
const char * descr
Definition: boot.c:45
#define memset(x, y, z)
Definition: compat.h:39
weight
Definition: sortkey.c:157
PCWSTR s2
Definition: shell32_main.h:38
#define TRACE(s)
Definition: solgame.cpp:4
CardRegion * from
Definition: spigame.cpp:19
float top
Definition: dcommon.idl:106
float bottom
Definition: dcommon.idl:108
float right
Definition: dcommon.idl:107
float left
Definition: dcommon.idl:105
UINT16 const * clusterMap
Definition: dwrite.idl:424
IDWriteFontFace * fontFace
Definition: dwrite.idl:405
DWRITE_GLYPH_OFFSET const * glyphOffsets
Definition: dwrite.idl:410
UINT32 bidiLevel
Definition: dwrite.idl:412
FLOAT fontEmSize
Definition: dwrite.idl:406
UINT16 const * glyphIndices
Definition: dwrite.idl:408
FLOAT const * glyphAdvances
Definition: dwrite.idl:409
UINT32 glyphCount
Definition: dwrite.idl:407
FLOAT widthIncludingTrailingWhitespace
Definition: dwrite_2.idl:40
UINT32 maxBidiReorderingDepth
Definition: dwrite_2.idl:44
UINT32 startPosition
Definition: dwrite.idl:475
DWRITE_FONT_FEATURE * features
Definition: dwrite.idl:544
FT_Pos x
Definition: ftimage.h:77
FT_Pos y
Definition: ftimage.h:78
Definition: dcommon.idl:28
long bottom
Definition: dcommon.idl:29
long right
Definition: dcommon.idl:29
long left
Definition: dcommon.idl:29
long top
Definition: dcommon.idl:29
Definition: cookie.c:202
Definition: http.c:7252
struct dwrite_textformat_data format
struct list inlineobjects
Definition: layout.c:246
unsigned int offset
Definition: layout.c:232
WCHAR * str
Definition: layout.c:227
IDWriteFontCollection * system_collection
Definition: layout.c:225
struct list strikethrough
Definition: layout.c:248
struct dwrite_textlayout::@321 text_source
USHORT recompute
Definition: layout.c:249
size_t lines_size
Definition: layout.c:260
DWRITE_LINE_BREAKPOINT * nominal_breakpoints
Definition: layout.c:251
struct list typographies
Definition: layout.c:239
IDWriteFactory7 * factory
Definition: layout.c:224
struct layout_cluster * clusters
Definition: layout.c:254
struct list spacing
Definition: layout.c:241
FLOAT minwidth
Definition: layout.c:257
DWRITE_TEXT_METRICS1 metrics
Definition: layout.c:262
DWRITE_CLUSTER_METRICS * clustermetrics
Definition: layout.c:255
struct list strike_ranges
Definition: layout.c:237
DWRITE_MATRIX transform
Definition: layout.c:269
DWRITE_OVERHANG_METRICS overhangs
Definition: layout.c:263
DWRITE_MEASURING_MODE measuringmode
Definition: layout.c:265
DWRITE_LINE_BREAKPOINT * actual_breakpoints
Definition: layout.c:252
unsigned int length
Definition: layout.c:233
IDWriteTextLayout4 IDWriteTextLayout4_iface
Definition: layout.c:218
IDWriteTextFormat3 IDWriteTextFormat3_iface
Definition: layout.c:219
struct layout_line * lines
Definition: layout.c:259
IDWriteTextAnalysisSink1 IDWriteTextAnalysisSink1_iface
Definition: layout.c:220
struct list underline_ranges
Definition: layout.c:238
IDWriteTextAnalysisSource1 IDWriteTextAnalysisSource1_iface
Definition: layout.c:221
struct list runs
Definition: layout.c:243
struct list effects
Definition: layout.c:240
struct list underlines
Definition: layout.c:247
struct dwrite_textformat_data format
Definition: layout.c:236
UINT32 cluster_count
Definition: layout.c:256
struct list eruns
Definition: layout.c:245
struct list ranges
Definition: layout.c:242
size_t capacity
Definition: layout.c:277
size_t count
Definition: layout.c:278
IDWriteTypography IDWriteTypography_iface
Definition: layout.c:273
DWRITE_FONT_FEATURE * features
Definition: layout.c:276
UINT16 length
Definition: layout.c:126
IDWriteInlineObject * object
Definition: layout.c:125
UINT32 position
Definition: layout.c:197
const struct layout_run * run
Definition: layout.c:196
IUnknown * effect
Definition: layout.c:173
D2D1_POINT_2F origin
Definition: layout.c:175
IDWriteInlineObject * object
Definition: layout.c:172
struct list entry
Definition: layout.c:171
D2D1_POINT_2F origin
Definition: layout.c:161
IUnknown * effect
Definition: layout.c:160
struct list entry
Definition: layout.c:155
const struct layout_run * run
Definition: layout.c:156
D2D1_RECT_F bbox
Definition: layout.c:167
UINT16 * clustermap
Definition: layout.c:164
float height
Definition: layout.c:202
float baseline
Definition: layout.c:203
DWRITE_LINE_METRICS1 metrics
Definition: layout.c:204
IDWriteInlineObject * object
Definition: layout.c:57
struct layout_range_attr_value::@318::@319 spacing
DWRITE_TEXT_RANGE range
Definition: layout.c:51
IDWriteFontCollection * collection
Definition: layout.c:62
IDWriteTypography * typography
Definition: layout.c:70
const WCHAR * locale
Definition: layout.c:63
IUnknown * effect
Definition: layout.c:58
DWRITE_FONT_STYLE style
Definition: layout.c:54
DWRITE_FONT_STRETCH stretch
Definition: layout.c:55
union layout_range_attr_value::@318 u
DWRITE_FONT_WEIGHT weight
Definition: layout.c:53
const WCHAR * fontfamily
Definition: layout.c:64
struct layout_range_header h
Definition: layout.c:103
struct list entry
Definition: layout.c:84
DWRITE_TEXT_RANGE range
Definition: layout.c:86
enum layout_range_kind kind
Definition: layout.c:85
struct layout_range_header h
Definition: layout.c:108
IUnknown * iface
Definition: layout.c:109
struct layout_range_header h
Definition: layout.c:113
BOOL pair_kerning
Definition: layout.c:96
FLOAT fontsize
Definition: layout.c:93
DWRITE_FONT_WEIGHT weight
Definition: layout.c:91
DWRITE_FONT_STRETCH stretch
Definition: layout.c:94
IDWriteInlineObject * object
Definition: layout.c:95
WCHAR * fontfamily
Definition: layout.c:99
IDWriteFontCollection * collection
Definition: layout.c:97
DWRITE_FONT_STYLE style
Definition: layout.c:92
struct list entry
Definition: layout.c:142
float height
Definition: layout.c:150
union layout_run::@320 u
enum layout_run_kind kind
Definition: layout.c:143
struct regular_layout_run regular
Definition: layout.c:147
unsigned int start_position
Definition: layout.c:151
float baseline
Definition: layout.c:149
struct list entry
Definition: layout.c:190
const struct layout_effective_run * run
Definition: layout.c:191
DWRITE_STRIKETHROUGH s
Definition: layout.c:192
const struct layout_effective_run * run
Definition: layout.c:185
DWRITE_UNDERLINE u
Definition: layout.c:186
struct list entry
Definition: layout.c:184
Definition: parser.c:49
Definition: list.h:15
Definition: name.c:39
DWRITE_GLYPH_RUN run
Definition: layout.c:131
DWRITE_GLYPH_OFFSET * offsets
Definition: layout.c:136
FLOAT * advances
Definition: layout.c:135
DWRITE_SCRIPT_ANALYSIS sa
Definition: layout.c:132
UINT32 glyphcount
Definition: layout.c:137
UINT16 * clustermap
Definition: layout.c:134
DWRITE_GLYPH_RUN_DESCRIPTION descr
Definition: layout.c:130
UINT16 * glyphs
Definition: layout.c:133
struct shaping_context::@322 user_features
DWRITE_SHAPING_TEXT_PROPERTIES * text_props
Definition: layout.c:829
DWRITE_SHAPING_GLYPH_PROPERTIES * glyph_props
Definition: layout.c:828
DWRITE_TYPOGRAPHIC_FEATURES ** features
Definition: layout.c:833
struct regular_layout_run * run
Definition: layout.c:827
unsigned int * range_lengths
Definition: layout.c:834
unsigned int range_count
Definition: layout.c:835
IDWriteTextAnalyzer2 * analyzer
Definition: layout.c:826
Definition: style.c:91
DMUS_IO_STYLE style
Definition: style.c:95
float x
Definition: hlsl_d3d11.c:34
float y
Definition: hlsl_d3d11.c:34
#define max(a, b)
Definition: svc.c:63
#define LIST_ENTRY(type)
Definition: queue.h:175
__inline int before(__u32 seq1, __u32 seq2)
Definition: tcpcore.h:2390
__inline int after(__u32 seq1, __u32 seq2)
Definition: tcpcore.h:2395
float FLOAT
Definition: typedefs.h:69
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t UINT32
Definition: typedefs.h:59
uint32_t ULONG
Definition: typedefs.h:59
Definition: pdh_main.c:64
#define WINAPI
Definition: msvc.h:6
#define E_NOT_SUFFICIENT_BUFFER
Definition: winerror.h:3437
#define E_NOINTERFACE
Definition: winerror.h:3479
#define const
Definition: zconf.h:233