Wine-Commits
Threads by month
- ----- 2026 -----
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
February 2019
- 1 participants
- 672 discussions
Dmitry Timoshkov : windowscodecs: Add support for converting to 8bppIndexed format.
by Alexandre Julliard Feb. 4, 2019
by Alexandre Julliard Feb. 4, 2019
Feb. 4, 2019
Module: wine
Branch: master
Commit: d6c2734d72e3cd530c16807324b61e981191b022
URL: https://source.winehq.org/git/wine.git/?a=commit;h=d6c2734d72e3cd530c168073…
Author: Dmitry Timoshkov <dmitry(a)baikal.ru>
Date: Fri Feb 1 16:47:18 2019 +0800
windowscodecs: Add support for converting to 8bppIndexed format.
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
Signed-off-by: Vincent Povirk <vincent(a)codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard(a)winehq.org>
---
dlls/windowscodecs/converter.c | 163 ++++++++++++++++++++++++++++++++++++-----
1 file changed, 146 insertions(+), 17 deletions(-)
diff --git a/dlls/windowscodecs/converter.c b/dlls/windowscodecs/converter.c
index 6e7bb8e..d6b62a6 100644
--- a/dlls/windowscodecs/converter.c
+++ b/dlls/windowscodecs/converter.c
@@ -76,7 +76,7 @@ typedef struct FormatConverter {
const struct pixelformatinfo *dst_format, *src_format;
WICBitmapDitherType dither;
double alpha_threshold;
- WICBitmapPaletteType palette_type;
+ IWICPalette *palette;
CRITICAL_SECTION lock; /* must be held when initialized */
} FormatConverter;
@@ -1219,11 +1219,99 @@ static HRESULT copypixels_to_8bppGray(struct FormatConverter *This, const WICRec
return hr;
}
+static UINT rgb_to_palette_index(BYTE bgr[3], WICColor *colors, UINT count)
+{
+ UINT best_diff, best_index, i;
+
+ best_diff = ~0;
+ best_index = 0;
+
+ for (i = 0; i < count; i++)
+ {
+ BYTE pal_r, pal_g, pal_b;
+ UINT diff_r, diff_g, diff_b, diff;
+
+ pal_r = colors[i] >> 16;
+ pal_g = colors[i] >> 8;
+ pal_b = colors[i];
+
+ diff_r = bgr[2] - pal_r;
+ diff_g = bgr[1] - pal_g;
+ diff_b = bgr[0] - pal_b;
+
+ diff = diff_r * diff_r + diff_g * diff_g + diff_b * diff_b;
+ if (diff == 0) return i;
+
+ if (diff < best_diff)
+ {
+ best_diff = diff;
+ best_index = i;
+ }
+ }
+
+ return best_index;
+}
+
+static HRESULT copypixels_to_8bppIndexed(struct FormatConverter *This, const WICRect *prc,
+ UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format)
+{
+ HRESULT hr;
+ BYTE *srcdata;
+ WICColor colors[256];
+ UINT srcstride, srcdatasize, count;
+
+ if (source_format == format_8bppIndexed)
+ {
+ if (prc)
+ return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
+
+ return S_OK;
+ }
+
+ if (!prc)
+ return copypixels_to_24bppBGR(This, NULL, cbStride, cbBufferSize, pbBuffer, source_format);
+
+ if (!This->palette) return WINCODEC_ERR_WRONGSTATE;
+
+ hr = IWICPalette_GetColors(This->palette, 256, colors, &count);
+ if (hr != S_OK) return hr;
+ if (!count) return WINCODEC_ERR_WRONGSTATE;
+
+ srcstride = 3 * prc->Width;
+ srcdatasize = srcstride * prc->Height;
+
+ srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
+ if (!srcdata) return E_OUTOFMEMORY;
+
+ hr = copypixels_to_24bppBGR(This, prc, srcstride, srcdatasize, srcdata, source_format);
+ if (SUCCEEDED(hr) && prc)
+ {
+ INT x, y;
+ BYTE *src = srcdata, *dst = pbBuffer;
+
+ for (y = 0; y < prc->Height; y++)
+ {
+ BYTE *bgr = src;
+
+ for (x = 0; x < prc->Width; x++)
+ {
+ dst[x] = rgb_to_palette_index(bgr, colors, count);
+ bgr += 3;
+ }
+ src += srcstride;
+ dst += cbStride;
+ }
+ }
+
+ HeapFree(GetProcessHeap(), 0, srcdata);
+ return hr;
+}
+
static const struct pixelformatinfo supported_formats[] = {
{format_1bppIndexed, &GUID_WICPixelFormat1bppIndexed, NULL},
{format_2bppIndexed, &GUID_WICPixelFormat2bppIndexed, NULL},
{format_4bppIndexed, &GUID_WICPixelFormat4bppIndexed, NULL},
- {format_8bppIndexed, &GUID_WICPixelFormat8bppIndexed, NULL},
+ {format_8bppIndexed, &GUID_WICPixelFormat8bppIndexed, copypixels_to_8bppIndexed},
{format_BlackWhite, &GUID_WICPixelFormatBlackWhite, NULL},
{format_2bppGray, &GUID_WICPixelFormat2bppGray, NULL},
{format_4bppGray, &GUID_WICPixelFormat4bppGray, NULL},
@@ -1300,6 +1388,7 @@ static ULONG WINAPI FormatConverter_Release(IWICFormatConverter *iface)
This->lock.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&This->lock);
if (This->source) IWICBitmapSource_Release(This->source);
+ if (This->palette) IWICPalette_Release(This->palette);
HeapFree(GetProcessHeap(), 0, This);
}
@@ -1348,10 +1437,16 @@ static HRESULT WINAPI FormatConverter_GetResolution(IWICFormatConverter *iface,
}
static HRESULT WINAPI FormatConverter_CopyPalette(IWICFormatConverter *iface,
- IWICPalette *pIPalette)
+ IWICPalette *palette)
{
- FIXME("(%p,%p): stub\n", iface, pIPalette);
- return E_NOTIMPL;
+ FormatConverter *This = impl_from_IWICFormatConverter(iface);
+
+ TRACE("(%p,%p)\n", iface, palette);
+
+ if (!palette) return E_INVALIDARG;
+ if (!This->palette) return WINCODEC_ERR_WRONGSTATE;
+
+ return IWICPalette_InitializeFromPalette(palette, This->palette);
}
static HRESULT WINAPI FormatConverter_CopyPixels(IWICFormatConverter *iface,
@@ -1384,19 +1479,52 @@ static HRESULT WINAPI FormatConverter_CopyPixels(IWICFormatConverter *iface,
}
static HRESULT WINAPI FormatConverter_Initialize(IWICFormatConverter *iface,
- IWICBitmapSource *pISource, REFWICPixelFormatGUID dstFormat, WICBitmapDitherType dither,
- IWICPalette *pIPalette, double alphaThresholdPercent, WICBitmapPaletteType paletteTranslate)
+ IWICBitmapSource *source, REFWICPixelFormatGUID dstFormat, WICBitmapDitherType dither,
+ IWICPalette *palette, double alpha_threshold, WICBitmapPaletteType palette_type)
{
FormatConverter *This = impl_from_IWICFormatConverter(iface);
const struct pixelformatinfo *srcinfo, *dstinfo;
- static INT fixme=0;
GUID srcFormat;
- HRESULT res=S_OK;
+ HRESULT res;
+
+ TRACE("(%p,%p,%s,%u,%p,%0.3f,%u)\n", iface, source, debugstr_guid(dstFormat),
+ dither, palette, alpha_threshold, palette_type);
+
+ if (!palette)
+ {
+ res = PaletteImpl_Create(&palette);
+ if (res != S_OK) return res;
+
+ switch (palette_type)
+ {
+ case WICBitmapPaletteTypeCustom:
+ IWICPalette_Release(palette);
+ palette = NULL;
+ res = S_OK;
+ break;
+
+ case WICBitmapPaletteTypeMedianCut:
+ {
+ UINT bpp;
+ res = get_pixelformat_bpp(dstFormat, &bpp);
+ if (res == S_OK && bpp <= 8)
+ res = IWICPalette_InitializeFromBitmap(palette, source, 1 << bpp, FALSE);
+ break;
+ }
- TRACE("(%p,%p,%s,%u,%p,%0.1f,%u)\n", iface, pISource, debugstr_guid(dstFormat),
- dither, pIPalette, alphaThresholdPercent, paletteTranslate);
+ default:
+ res = IWICPalette_InitializePredefined(palette, palette_type, FALSE);
+ break;
+ }
- if (pIPalette && !fixme++) FIXME("ignoring palette\n");
+ if (res != S_OK)
+ {
+ IWICPalette_Release(palette);
+ return res;
+ }
+ }
+ else
+ IWICPalette_AddRef(palette);
EnterCriticalSection(&This->lock);
@@ -1406,7 +1534,7 @@ static HRESULT WINAPI FormatConverter_Initialize(IWICFormatConverter *iface,
goto end;
}
- res = IWICBitmapSource_GetPixelFormat(pISource, &srcFormat);
+ res = IWICBitmapSource_GetPixelFormat(source, &srcFormat);
if (FAILED(res)) goto end;
srcinfo = get_formatinfo(&srcFormat);
@@ -1427,13 +1555,13 @@ static HRESULT WINAPI FormatConverter_Initialize(IWICFormatConverter *iface,
if (dstinfo->copy_function)
{
- IWICBitmapSource_AddRef(pISource);
+ IWICBitmapSource_AddRef(source);
This->src_format = srcinfo;
This->dst_format = dstinfo;
This->dither = dither;
- This->alpha_threshold = alphaThresholdPercent;
- This->palette_type = paletteTranslate;
- This->source = pISource;
+ This->alpha_threshold = alpha_threshold;
+ This->palette = palette;
+ This->source = source;
}
else
{
@@ -1512,6 +1640,7 @@ HRESULT FormatConverter_CreateInstance(REFIID iid, void** ppv)
This->IWICFormatConverter_iface.lpVtbl = &FormatConverter_Vtbl;
This->ref = 1;
This->source = NULL;
+ This->palette = NULL;
InitializeCriticalSection(&This->lock);
This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": FormatConverter.lock");
1
0
Nikolay Sivov : dwrite: Implement pair adjustment, GPOS lookup 2.
by Alexandre Julliard Feb. 4, 2019
by Alexandre Julliard Feb. 4, 2019
Feb. 4, 2019
Module: wine
Branch: master
Commit: 9b2ff6d2f1f3e94ebba1dc190be11cfccf03b0bb
URL: https://source.winehq.org/git/wine.git/?a=commit;h=9b2ff6d2f1f3e94ebba1dc19…
Author: Nikolay Sivov <nsivov(a)codeweavers.com>
Date: Fri Feb 1 13:48:10 2019 +0300
dwrite: Implement pair adjustment, GPOS lookup 2.
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard(a)winehq.org>
---
dlls/dwrite/opentype.c | 201 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 201 insertions(+)
diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c
index 8cc45e4..f3c2043 100644
--- a/dlls/dwrite/opentype.c
+++ b/dlls/dwrite/opentype.c
@@ -586,6 +586,41 @@ struct ot_gpos_singlepos_format2
WORD values[1];
};
+struct ot_gpos_pairvalue
+{
+ WORD second_glyph;
+ BYTE data[1];
+};
+
+struct ot_gpos_pairset
+{
+ WORD pairvalue_count;
+ struct ot_gpos_pairvalue pairvalues[1];
+};
+
+struct ot_gpos_pairpos_format1
+{
+ WORD format;
+ WORD coverage;
+ WORD value_format1;
+ WORD value_format2;
+ WORD pairset_count;
+ WORD pairsets[1];
+};
+
+struct ot_gpos_pairpos_format2
+{
+ WORD format;
+ WORD coverage;
+ WORD value_format1;
+ WORD value_format2;
+ WORD class_def1;
+ WORD class_def2;
+ WORD class1_count;
+ WORD class2_count;
+ WORD values[1];
+};
+
typedef struct {
WORD SubstFormat;
WORD Coverage;
@@ -2929,6 +2964,21 @@ static BOOL glyph_iterator_match(const struct glyph_iterator *iter)
return TRUE;
}
+static BOOL glyph_iterator_next(struct glyph_iterator *iter)
+{
+ while (iter->pos + iter->len < iter->context->glyph_count)
+ {
+ ++iter->pos;
+ if (glyph_iterator_match(iter))
+ {
+ --iter->len;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
static BOOL opentype_layout_apply_gpos_single_adjustment(struct scriptshaping_context *context,
struct glyph_iterator *iter, const struct lookup *lookup)
{
@@ -2985,9 +3035,160 @@ static BOOL opentype_layout_apply_gpos_single_adjustment(struct scriptshaping_co
return FALSE;
}
+static int gpos_pair_adjustment_compare_format1(const void *g, const void *r)
+{
+ const struct ot_gpos_pairvalue *pairvalue = r;
+ UINT16 second_glyph = GET_BE_WORD(pairvalue->second_glyph);
+ return *(UINT16 *)g - second_glyph;
+}
+
static BOOL opentype_layout_apply_gpos_pair_adjustment(struct scriptshaping_context *context,
struct glyph_iterator *iter, const struct lookup *lookup)
{
+ struct scriptshaping_cache *cache = context->cache;
+ unsigned int i, first_glyph, second_glyph;
+ struct glyph_iterator iter_pair;
+ WORD format, coverage;
+
+ glyph_iterator_init(context, iter->flags, iter->pos, 1, &iter_pair);
+ if (!glyph_iterator_next(&iter_pair))
+ return FALSE;
+
+ if (context->is_rtl)
+ {
+ first_glyph = iter_pair.pos;
+ second_glyph = iter->pos;
+ }
+ else
+ {
+ first_glyph = iter->pos;
+ second_glyph = iter_pair.pos;
+ }
+
+ for (i = 0; i < lookup->subtable_count; ++i)
+ {
+ unsigned int subtable_offset = opentype_layout_get_gpos_subtable(cache, lookup->offset, i);
+ WORD value_format1, value_format2, value_len1, value_len2;
+ unsigned int coverage_index;
+
+ format = table_read_be_word(&cache->gpos.table, subtable_offset);
+
+ coverage = table_read_be_word(&cache->gpos.table, subtable_offset +
+ FIELD_OFFSET(struct ot_gpos_pairpos_format1, coverage));
+ if (!coverage)
+ continue;
+
+ coverage_index = opentype_layout_is_glyph_covered(&cache->gpos.table, subtable_offset +
+ coverage, context->u.pos.glyphs[first_glyph]);
+ if (coverage_index == GLYPH_NOT_COVERED)
+ continue;
+
+ if (format == 1)
+ {
+ const struct ot_gpos_pairpos_format1 *format1;
+ WORD pairset_count = table_read_be_word(&cache->gpos.table, subtable_offset +
+ FIELD_OFFSET(struct ot_gpos_pairpos_format1, pairset_count));
+ unsigned int pairvalue_len, pairset_offset;
+ const struct ot_gpos_pairset *pairset;
+ const WORD *pairvalue;
+ WORD pairvalue_count;
+
+ if (!pairset_count || coverage_index >= pairset_count)
+ continue;
+
+ format1 = table_read_ensure(&cache->gpos.table, subtable_offset,
+ FIELD_OFFSET(struct ot_gpos_pairpos_format1, pairsets[pairset_count]));
+ if (!format1)
+ continue;
+
+ /* Ordered paired values. */
+ pairvalue_count = table_read_be_word(&cache->gpos.table, subtable_offset +
+ GET_BE_WORD(format1->pairsets[coverage_index]));
+ if (!pairvalue_count)
+ continue;
+
+ /* Structure length is variable, but does not change across the subtable. */
+ value_format1 = GET_BE_WORD(format1->value_format1) & 0xff;
+ value_format2 = GET_BE_WORD(format1->value_format2) & 0xff;
+
+ value_len1 = dwrite_popcount(value_format1);
+ value_len2 = dwrite_popcount(value_format2);
+ pairvalue_len = FIELD_OFFSET(struct ot_gpos_pairvalue, data) + value_len1 * sizeof(WORD) +
+ value_len2 * sizeof(WORD);
+
+ pairset_offset = subtable_offset + GET_BE_WORD(format1->pairsets[coverage_index]);
+ pairset = table_read_ensure(&cache->gpos.table, subtable_offset + pairset_offset,
+ pairvalue_len * pairvalue_count);
+ if (!pairset)
+ continue;
+
+ pairvalue = bsearch(&context->u.pos.glyphs[second_glyph], pairset->pairvalues, pairvalue_count,
+ pairvalue_len, gpos_pair_adjustment_compare_format1);
+ if (!pairvalue)
+ continue;
+
+ pairvalue += 1; /* Skip SecondGlyph. */
+ opentype_layout_apply_gpos_value(context, pairset_offset, value_format1, pairvalue, first_glyph);
+ opentype_layout_apply_gpos_value(context, pairset_offset, value_format2, pairvalue + value_len1,
+ second_glyph);
+
+ iter->pos = iter_pair.pos;
+ if (value_len2)
+ iter->pos++;
+
+ return TRUE;
+ }
+ else if (format == 2)
+ {
+ const struct ot_gpos_pairpos_format2 *format2;
+ WORD class1_count, class2_count;
+ unsigned int class1, class2;
+
+ value_format1 = table_read_be_word(&cache->gpos.table, subtable_offset +
+ FIELD_OFFSET(struct ot_gpos_pairpos_format2, value_format1)) & 0xff;
+ value_format2 = table_read_be_word(&cache->gpos.table, subtable_offset +
+ FIELD_OFFSET(struct ot_gpos_pairpos_format2, value_format2)) & 0xff;
+
+ class1_count = table_read_be_word(&cache->gpos.table, subtable_offset +
+ FIELD_OFFSET(struct ot_gpos_pairpos_format2, class1_count));
+ class2_count = table_read_be_word(&cache->gpos.table, subtable_offset +
+ FIELD_OFFSET(struct ot_gpos_pairpos_format2, class2_count));
+
+ value_len1 = dwrite_popcount(value_format1);
+ value_len2 = dwrite_popcount(value_format2);
+
+ format2 = table_read_ensure(&cache->gpos.table, subtable_offset,
+ FIELD_OFFSET(struct ot_gpos_pairpos_format2,
+ values[class1_count * class2_count * (value_len1 + value_len2)]));
+ if (!format2)
+ continue;
+
+ class1 = opentype_layout_get_glyph_class(&cache->gpos.table, subtable_offset + GET_BE_WORD(format2->class_def1),
+ context->u.pos.glyphs[first_glyph]);
+ class2 = opentype_layout_get_glyph_class(&cache->gpos.table, subtable_offset + GET_BE_WORD(format2->class_def2),
+ context->u.pos.glyphs[second_glyph]);
+
+ if (class1 < class1_count && class2 < class2_count)
+ {
+ const WCHAR *values = &format2->values[(class1 * class2_count + class2) * (value_len1 + value_len2)];
+ opentype_layout_apply_gpos_value(context, subtable_offset, value_format1, values, first_glyph);
+ opentype_layout_apply_gpos_value(context, subtable_offset, value_format2, values + value_len1,
+ second_glyph);
+
+ iter->pos = iter_pair.pos;
+ if (value_len2)
+ iter->pos++;
+
+ return TRUE;
+ }
+ }
+ else
+ {
+ WARN("Unknown pair adjustment format %u.\n", format);
+ continue;
+ }
+ }
+
return FALSE;
}
1
0