1/* 2 * Copyright 2009, Haiku, Inc. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Michael Lotz <mmlr@mlotz.ch> 7 * Fran��ois Revol <revol@free.fr> 8 */ 9 10#include "CanvasMessage.h" 11 12#include "DrawState.h" 13#include "ServerBitmap.h" 14#include "ServerCursor.h" 15 16#include <Bitmap.h> 17#include <Font.h> 18#include <View.h> 19 20#include <Gradient.h> 21#include <GradientLinear.h> 22#include <GradientRadial.h> 23#include <GradientRadialFocus.h> 24#include <GradientDiamond.h> 25#include <GradientConic.h> 26 27#include <new> 28 29 30status_t 31CanvasMessage::NextMessage(uint16& code) 32{ 33 if (fDataLeft > 0) { 34 // discard remainder of message 35 int32 readSize = fSource->Read(NULL, fDataLeft); 36 if (readSize < 0) 37 return readSize; 38 } 39 40 static const uint32 kHeaderSize = sizeof(uint16) + sizeof(uint32); 41 42 fDataLeft = kHeaderSize; 43 Read(code); 44 uint32 dataLeft; 45 status_t result = Read(dataLeft); 46 if (result != B_OK) 47 return result; 48 49 if (dataLeft < kHeaderSize) 50 return B_ERROR; 51 52 fDataLeft = dataLeft - kHeaderSize; 53 fCode = code; 54 return B_OK; 55} 56 57 58void 59CanvasMessage::Cancel() 60{ 61 fAvailable += fWriteIndex; 62 fWriteIndex = 0; 63} 64 65 66void 67CanvasMessage::AddBitmap(const ServerBitmap& bitmap, bool minimal) 68{ 69 //TODO:send PNG / as data: or as http: url 70 Add(bitmap.Width()); 71 Add(bitmap.Height()); 72 Add(bitmap.BytesPerRow()); 73 74 if (!minimal) { 75 Add(bitmap.ColorSpace()); 76 Add(bitmap.Flags()); 77 } 78 79 uint32 bitsLength = bitmap.BitsLength(); 80 Add(bitsLength); 81 82 if (!_MakeSpace(bitsLength)) 83 return; 84 85 memcpy(fBuffer + fWriteIndex, bitmap.Bits(), bitsLength); 86 fWriteIndex += bitsLength; 87 fAvailable -= bitsLength; 88} 89 90 91void 92CanvasMessage::AddFont(const ServerFont& font) 93{ 94 //TODO:Use TTF/WOFF URL 95 Add(font.Direction()); 96 Add((uint8)font.Encoding()); 97 Add(font.Flags()); 98 Add((uint8)font.Spacing()); 99 Add(font.Shear()); 100 Add(font.Rotation()); 101 Add(font.FalseBoldWidth()); 102 Add(font.Size()); 103 Add(font.Face()); 104 Add(font.GetFamilyAndStyle()); 105} 106 107 108void 109CanvasMessage::AddDrawState(const DrawState& drawState) 110{ 111 Add(drawState.PenSize()); 112 Add(drawState.SubPixelPrecise()); 113 Add(drawState.GetDrawingMode()); 114 Add(drawState.AlphaSrcMode()); 115 Add(drawState.AlphaFncMode()); 116 AddPattern(drawState.GetPattern()); 117 Add(drawState.LineCapMode()); 118 Add(drawState.LineJoinMode()); 119 Add(drawState.MiterLimit()); 120 Add(drawState.HighColor()); 121 Add(drawState.LowColor()); 122} 123 124 125void 126CanvasMessage::AddArrayLine(const ViewLineArrayInfo& line) 127{ 128 Add(line.startPoint); 129 Add(line.endPoint); 130 Add(line.color); 131} 132 133 134void 135CanvasMessage::AddCursor(const ServerCursor& cursor) 136{ 137 //TODO:send as .cur data: 138 Add(cursor.GetHotSpot()); 139 AddBitmap(cursor); 140} 141 142 143void 144CanvasMessage::AddPattern(const Pattern& pattern) 145{ 146 Add(pattern.GetPattern()); 147} 148 149 150void 151CanvasMessage::AddGradient(const BGradient& gradient) 152{ 153 Add(gradient.GetType()); 154 155 switch (gradient.GetType()) { 156 case BGradient::TYPE_NONE: 157 break; 158 159 case BGradient::TYPE_LINEAR: 160 { 161 const BGradientLinear* linear 162 = dynamic_cast<const BGradientLinear *>(&gradient); 163 if (linear == NULL) 164 return; 165 166 Add(linear->Start()); 167 Add(linear->End()); 168 break; 169 } 170 171 case BGradient::TYPE_RADIAL: 172 { 173 const BGradientRadial* radial 174 = dynamic_cast<const BGradientRadial *>(&gradient); 175 if (radial == NULL) 176 return; 177 178 Add(radial->Center()); 179 Add(radial->Radius()); 180 break; 181 } 182 183 case BGradient::TYPE_RADIAL_FOCUS: 184 { 185 const BGradientRadialFocus* radialFocus 186 = dynamic_cast<const BGradientRadialFocus *>(&gradient); 187 if (radialFocus == NULL) 188 return; 189 190 Add(radialFocus->Center()); 191 Add(radialFocus->Focal()); 192 Add(radialFocus->Radius()); 193 break; 194 } 195 196 case BGradient::TYPE_DIAMOND: 197 { 198 const BGradientDiamond* diamond 199 = dynamic_cast<const BGradientDiamond *>(&gradient); 200 if (diamond == NULL) 201 return; 202 203 Add(diamond->Center()); 204 break; 205 } 206 207 case BGradient::TYPE_CONIC: 208 { 209 const BGradientConic* conic 210 = dynamic_cast<const BGradientConic *>(&gradient); 211 if (conic == NULL) 212 return; 213 214 Add(conic->Center()); 215 Add(conic->Angle()); 216 break; 217 } 218 } 219 220 int32 stopCount = gradient.CountColorStops(); 221 Add(stopCount); 222 223 for (int32 i = 0; i < stopCount; i++) { 224 BGradient::ColorStop* stop = gradient.ColorStopAt(i); 225 if (stop == NULL) 226 return; 227 228 Add(stop->color); 229 Add(stop->offset); 230 } 231} 232 233 234status_t 235CanvasMessage::ReadString(char** _string, size_t& _length) 236{ 237 uint32 length; 238 status_t result = Read(length); 239 if (result != B_OK) 240 return result; 241 242 if (length > fDataLeft) 243 return B_ERROR; 244 245 char *string = (char *)malloc(length + 1); 246 if (string == NULL) 247 return B_NO_MEMORY; 248 249 int32 readSize = fSource->Read(string, length); 250 if (readSize < 0) { 251 free(string); 252 return readSize; 253 } 254 255 if ((uint32)readSize != length) { 256 free(string); 257 return B_ERROR; 258 } 259 260 fDataLeft -= readSize; 261 262 string[length] = 0; 263 *_string = string; 264 _length = length; 265 return B_OK; 266} 267 268 269status_t 270CanvasMessage::ReadBitmap(BBitmap** _bitmap, bool minimal, 271 color_space colorSpace, uint32 flags) 272{ 273 uint32 bitsLength; 274 int32 width, height, bytesPerRow; 275 276 Read(width); 277 Read(height); 278 Read(bytesPerRow); 279 280 if (!minimal) { 281 Read(colorSpace); 282 Read(flags); 283 } 284 285 Read(bitsLength); 286 287 if (bitsLength > fDataLeft) 288 return B_ERROR; 289 290#ifndef CLIENT_COMPILE 291 flags = B_BITMAP_NO_SERVER_LINK; 292#endif 293 294 BBitmap *bitmap = new(std::nothrow) BBitmap( 295 BRect(0, 0, width - 1, height - 1), flags, colorSpace, bytesPerRow); 296 if (bitmap == NULL) 297 return B_NO_MEMORY; 298 299 status_t result = bitmap->InitCheck(); 300 if (result != B_OK) { 301 delete bitmap; 302 return result; 303 } 304 305 if (bitmap->BitsLength() < (int32)bitsLength) { 306 delete bitmap; 307 return B_ERROR; 308 } 309 310 int32 readSize = fSource->Read(bitmap->Bits(), bitsLength); 311 if ((uint32)readSize != bitsLength) { 312 delete bitmap; 313 return readSize < 0 ? readSize : B_ERROR; 314 } 315 316 fDataLeft -= readSize; 317 *_bitmap = bitmap; 318 return B_OK; 319} 320 321 322status_t 323CanvasMessage::ReadFontState(BFont& font) 324{ 325 uint8 encoding, spacing; 326 uint16 face; 327 uint32 flags, familyAndStyle; 328 font_direction direction; 329 float falseBoldWidth, rotation, shear, size; 330 331 Read(direction); 332 Read(encoding); 333 Read(flags); 334 Read(spacing); 335 Read(shear); 336 Read(rotation); 337 Read(falseBoldWidth); 338 Read(size); 339 Read(face); 340 status_t result = Read(familyAndStyle); 341 if (result != B_OK) 342 return result; 343 344 font.SetFamilyAndStyle(familyAndStyle); 345 font.SetEncoding(encoding); 346 font.SetFlags(flags); 347 font.SetSpacing(spacing); 348 font.SetShear(shear); 349 font.SetRotation(rotation); 350 font.SetFalseBoldWidth(falseBoldWidth); 351 font.SetSize(size); 352 font.SetFace(face); 353 return B_OK; 354} 355 356 357status_t 358CanvasMessage::ReadViewState(BView& view, ::pattern& pattern) 359{ 360 bool subPixelPrecise; 361 float penSize, miterLimit; 362 drawing_mode drawingMode; 363 source_alpha sourceAlpha; 364 alpha_function alphaFunction; 365 cap_mode capMode; 366 join_mode joinMode; 367 rgb_color highColor, lowColor; 368 369 Read(penSize); 370 Read(subPixelPrecise); 371 Read(drawingMode); 372 Read(sourceAlpha); 373 Read(alphaFunction); 374 Read(pattern); 375 Read(capMode); 376 Read(joinMode); 377 Read(miterLimit); 378 Read(highColor); 379 status_t result = Read(lowColor); 380 if (result != B_OK) 381 return result; 382 383 uint32 flags = view.Flags() & ~B_SUBPIXEL_PRECISE; 384 view.SetFlags(flags | (subPixelPrecise ? B_SUBPIXEL_PRECISE : 0)); 385 view.SetPenSize(penSize); 386 view.SetDrawingMode(drawingMode); 387 view.SetBlendingMode(sourceAlpha, alphaFunction); 388 view.SetLineMode(capMode, joinMode, miterLimit); 389 view.SetHighColor(highColor); 390 view.SetLowColor(lowColor); 391 return B_OK; 392} 393 394 395status_t 396CanvasMessage::ReadGradient(BGradient** _gradient) 397{ 398 BGradient::Type type; 399 Read(type); 400 401 BGradient *gradient = NULL; 402 switch (type) { 403 case BGradient::TYPE_NONE: 404 break; 405 406 case BGradient::TYPE_LINEAR: 407 { 408 BPoint start, end; 409 410 Read(start); 411 Read(end); 412 413 gradient = new(std::nothrow) BGradientLinear(start, end); 414 break; 415 } 416 417 case BGradient::TYPE_RADIAL: 418 { 419 BPoint center; 420 float radius; 421 422 Read(center); 423 Read(radius); 424 425 gradient = new(std::nothrow) BGradientRadial(center, radius); 426 break; 427 } 428 429 case BGradient::TYPE_RADIAL_FOCUS: 430 { 431 BPoint center, focal; 432 float radius; 433 434 Read(center); 435 Read(focal); 436 Read(radius); 437 438 gradient = new(std::nothrow) BGradientRadialFocus(center, radius, 439 focal); 440 break; 441 } 442 443 case BGradient::TYPE_DIAMOND: 444 { 445 BPoint center; 446 447 Read(center); 448 449 gradient = new(std::nothrow) BGradientDiamond(center); 450 break; 451 } 452 453 case BGradient::TYPE_CONIC: 454 { 455 BPoint center; 456 float angle; 457 458 Read(center); 459 Read(angle); 460 461 gradient = new(std::nothrow) BGradientConic(center, angle); 462 break; 463 } 464 } 465 466 if (gradient == NULL) 467 return B_NO_MEMORY; 468 469 int32 stopCount; 470 status_t result = Read(stopCount); 471 if (result != B_OK) { 472 delete gradient; 473 return result; 474 } 475 476 for (int32 i = 0; i < stopCount; i++) { 477 rgb_color color; 478 float offset; 479 480 Read(color); 481 result = Read(offset); 482 if (result != B_OK) 483 return result; 484 485 gradient->AddColor(color, offset); 486 } 487 488 *_gradient = gradient; 489 return B_OK; 490} 491 492 493status_t 494CanvasMessage::ReadArrayLine(BPoint& startPoint, BPoint& endPoint, 495 rgb_color& color) 496{ 497 Read(startPoint); 498 Read(endPoint); 499 return Read(color); 500} 501