Enable chrome with aura for tizen
[platform/framework/web/chromium-efl.git] / printing / metafile_skia_unittest.cc
1 // Copyright 2018 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "printing/metafile_skia.h"
6
7 #include <utility>
8
9 #include "build/build_config.h"
10 #include "cc/paint/paint_record.h"
11 #include "printing/common/metafile_utils.h"
12 #include "printing/mojom/print.mojom.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "third_party/skia/include/core/SkBitmap.h"
15 #include "third_party/skia/include/core/SkCanvas.h"
16 #include "third_party/skia/include/core/SkPaint.h"
17 #include "third_party/skia/include/core/SkPicture.h"
18 #include "third_party/skia/include/core/SkPictureRecorder.h"
19 #include "third_party/skia/include/core/SkRect.h"
20 #include "third_party/skia/include/core/SkRefCnt.h"
21 #include "third_party/skia/include/core/SkSerialProcs.h"
22 #include "third_party/skia/include/core/SkSize.h"
23 #include "third_party/skia/include/core/SkStream.h"
24 #include "third_party/skia/include/core/SkSurfaceProps.h"
25 #include "third_party/skia/include/core/SkTextBlob.h"
26
27 namespace printing {
28
29 TEST(MetafileSkiaTest, TestFrameContent) {
30   constexpr int kPictureSideLen = 100;
31   constexpr int kPageSideLen = 150;
32
33   // Create a placeholder picture.
34   sk_sp<SkPicture> pic_holder = SkPicture::MakePlaceholder(
35       SkRect::MakeXYWH(0, 0, kPictureSideLen, kPictureSideLen));
36
37   // Create the page with nested content which is the placeholder and will be
38   // replaced later.
39   sk_sp<cc::PaintRecord> record = sk_make_sp<cc::PaintRecord>();
40   cc::PaintFlags flags;
41   flags.setColor(SK_ColorWHITE);
42   const SkRect page_rect = SkRect::MakeXYWH(0, 0, kPageSideLen, kPageSideLen);
43   record->push<cc::DrawRectOp>(page_rect, flags);
44   const uint32_t content_id = pic_holder->uniqueID();
45   record->push<cc::CustomDataOp>(content_id);
46   SkSize page_size = SkSize::Make(kPageSideLen, kPageSideLen);
47
48   // Finish creating the entire metafile.
49   MetafileSkia metafile(mojom::SkiaDocumentType::kMSKP, 1);
50   metafile.AppendPage(page_size, std::move(record));
51   metafile.AppendSubframeInfo(content_id, base::UnguessableToken::Create(),
52                               std::move(pic_holder));
53   metafile.FinishFrameContent();
54   SkStreamAsset* metafile_stream = metafile.GetPdfData();
55   ASSERT_TRUE(metafile_stream);
56
57   // Draw a 100 by 100 red square which will be the actual content of
58   // the placeholder.
59   SkPictureRecorder recorder;
60   SkCanvas* canvas = recorder.beginRecording(kPictureSideLen, kPictureSideLen);
61   SkPaint paint;
62   paint.setStyle(SkPaint::kFill_Style);
63   paint.setColor(SK_ColorRED);
64   paint.setAlpha(SK_AlphaOPAQUE);
65   canvas->drawRect(SkRect::MakeXYWH(0, 0, kPictureSideLen, kPictureSideLen),
66                    paint);
67   sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
68   EXPECT_TRUE(picture);
69
70   // Get the complete picture by replacing the placeholder.
71   PictureDeserializationContext subframes;
72   subframes[content_id] = picture;
73   SkDeserialProcs procs = DeserializationProcs(&subframes, nullptr);
74   sk_sp<SkPicture> pic = SkPicture::MakeFromStream(metafile_stream, &procs);
75   ASSERT_TRUE(pic);
76
77   // Verify the resultant picture is as expected by comparing the sizes and
78   // detecting the color inside and outside of the square area.
79   EXPECT_TRUE(pic->cullRect() == page_rect);
80   SkBitmap bitmap;
81   bitmap.allocN32Pixels(kPageSideLen, kPageSideLen);
82   SkCanvas bitmap_canvas(bitmap, SkSurfaceProps{});
83   pic->playback(&bitmap_canvas);
84   // Check top left pixel color of the red square.
85   EXPECT_EQ(bitmap.getColor(0, 0), SK_ColorRED);
86   // Check bottom right pixel of the red square.
87   EXPECT_EQ(bitmap.getColor(kPictureSideLen - 1, kPictureSideLen - 1),
88             SK_ColorRED);
89   // Check inside of the red square.
90   EXPECT_EQ(bitmap.getColor(kPictureSideLen / 2, kPictureSideLen / 2),
91             SK_ColorRED);
92   // Check outside of the red square.
93   EXPECT_EQ(bitmap.getColor(kPictureSideLen, kPictureSideLen), SK_ColorWHITE);
94 }
95
96 TEST(MetafileSkiaTest, TestMultiPictureDocumentTypefaces) {
97   constexpr int kPictureSideLen = 100;
98   constexpr int kPageSideLen = 150;
99   constexpr int kDocumentCookie = 1;
100   constexpr int kNumDocumentPages = 2;
101
102   // The content tracking for serialization/deserialization.
103   ContentProxySet serialize_typeface_ctx;
104   PictureDeserializationContext subframes;
105   TypefaceDeserializationContext typefaces;
106   SkDeserialProcs procs = DeserializationProcs(&subframes, &typefaces);
107
108   // The typefaces which will be reused across the multiple (duplicate) pages.
109   constexpr char kTypefaceName1[] = "sans-serif";
110 #if BUILDFLAG(IS_WIN)
111   constexpr char kTypefaceName2[] = "Courier New";
112 #else
113   constexpr char kTypefaceName2[] = "monospace";
114 #endif
115   constexpr size_t kNumTypefaces = 2;
116   sk_sp<SkTypeface> typeface1 =
117       SkTypeface::MakeFromName(kTypefaceName1, SkFontStyle());
118   sk_sp<SkTypeface> typeface2 =
119       SkTypeface::MakeFromName(kTypefaceName2, SkFontStyle());
120   const SkFont font1 = SkFont(typeface1, 10);
121   const SkFont font2 = SkFont(typeface2, 12);
122
123   // Node IDs for the text, which will increase for each text blob added.
124   cc::NodeId node_id = 7;
125
126   // All text can just be black.
127   cc::PaintFlags flags_text;
128   flags_text.setColor(SK_ColorBLACK);
129
130   // Mark the text on white pages, each of the same size.
131   cc::PaintFlags flags;
132   flags.setColor(SK_ColorWHITE);
133   const SkRect page_rect = SkRect::MakeXYWH(0, 0, kPageSideLen, kPageSideLen);
134   SkSize page_size = SkSize::Make(kPageSideLen, kPageSideLen);
135
136   for (int i = 0; i < kNumDocumentPages; i++) {
137     MetafileSkia metafile(mojom::SkiaDocumentType::kMSKP, kDocumentCookie);
138
139     // When the stream is serialized inside FinishFrameContent(), any typeface
140     // which is used on any page will be serialized only once by the first
141     // page's metafile which needed it.  Any subsequent page that reuses the
142     // same typeface will rely upon `serialize_typeface_ctx` which is used by
143     // printing::SerializeOopTypeface() to optimize away the need to resend.
144     metafile.UtilizeTypefaceContext(&serialize_typeface_ctx);
145
146     sk_sp<SkPicture> pic_holder = SkPicture::MakePlaceholder(
147         SkRect::MakeXYWH(0, 0, kPictureSideLen, kPictureSideLen));
148
149     // Create the page for the text content.
150     sk_sp<cc::PaintRecord> record = sk_make_sp<cc::PaintRecord>();
151     record->push<cc::DrawRectOp>(page_rect, flags);
152     const uint32_t content_id = pic_holder->uniqueID();
153     record->push<cc::CustomDataOp>(content_id);
154
155     // Mark the page with some text using multiple fonts.
156     // Use the first font.
157     sk_sp<SkTextBlob> text_blob1 = SkTextBlob::MakeFromString("foo", font1);
158     record->push<cc::DrawTextBlobOp>(text_blob1, 0.0f, 0.0f, ++node_id,
159                                      flags_text);
160
161     // Use the second font.
162     sk_sp<SkTextBlob> text_blob2 = SkTextBlob::MakeFromString("bar", font2);
163     record->push<cc::DrawTextBlobOp>(text_blob2, 0.0f, 0.0f, ++node_id,
164                                      flags_text);
165
166     // Reuse the first font again on same page.
167     sk_sp<SkTextBlob> text_blob3 = SkTextBlob::MakeFromString("bar", font2);
168     record->push<cc::DrawTextBlobOp>(text_blob3, 0.0f, 0.0f, ++node_id,
169                                      flags_text);
170
171     metafile.AppendPage(page_size, std::move(record));
172     metafile.AppendSubframeInfo(content_id, base::UnguessableToken::Create(),
173                                 std::move(pic_holder));
174     metafile.FinishFrameContent();
175     SkStreamAsset* metafile_stream = metafile.GetPdfData();
176     ASSERT_TRUE(metafile_stream);
177
178     // Deserialize the stream.  Any given typeface is expected to appear only
179     // once in the stream, so the deserialization context of `typefaces` bundled
180     // with `procs` should be empty the first time through, and afterwards
181     // there should never be more than the number of unique typefaces we used,
182     // regardless of number of pages.
183     EXPECT_EQ(typefaces.size(), i ? kNumTypefaces : 0);
184     ASSERT_TRUE(SkPicture::MakeFromStream(metafile_stream, &procs));
185     EXPECT_EQ(typefaces.size(), kNumTypefaces);
186   }
187 }
188
189 }  // namespace printing